Package eas.startSetup.marbBuilder.traceBetrachter

Source Code of eas.startSetup.marbBuilder.traceBetrachter.GuiSimulation

/*
* Datei:          GuiSimulation.java
* Autor(en):      Lukas König
* Java-Version:   6.0
* Erstellt (vor): 09.05.2008
*
* (c) This file and the EAS (Easy Agent Simulation) framework containing it
* is protected by Creative Commons by-nc-sa license. Any altered or
* further developed versions of this file have to meet the agreements
* stated by the license conditions.
*
* In a nutshell
* -------------
* You are free:
* - to Share -- to copy, distribute and transmit the work
* - to Remix -- to adapt the work
*
* Under the following conditions:
* - Attribution -- You must attribute the work in the manner specified by the
*   author or licensor (but not in any way that suggests that they endorse
*   you or your use of the work).
* - Noncommercial -- You may not use this work for commercial purposes.
* - Share Alike -- If you alter, transform, or build upon this work, you may
*   distribute the resulting work only under the same or a similar license to
*   this one.
*
* + Detailed license conditions (Germany):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/de/
* + Detailed license conditions (unported):
*   http://creativecommons.org/licenses/by-nc-sa/3.0/deed.en
*
* This header must be placed in the beginning of any version of this file.
*/

package eas.startSetup.marbBuilder.traceBetrachter;

import java.awt.Frame;
import java.awt.Graphics;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferedImage;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Observable;
import java.util.Observer;

import eas.math.geometry.Pixel2D_08Bit;
import eas.math.geometry.Vector2D;
import eas.miscellaneous.StaticMethods;
import eas.plugins.standard.eaPlugin.xmlRecording.XMLAufnLesen;
import eas.simulation.ConstantsSimulation;
import eas.startSetup.ParCollection;
import eas.startSetup.marbBuilder.SteuerFenster;


/**
* Klasse zur Darstellung einer Simulation in Echtzeit.
*
* @author Lukas König
*/
public class GuiSimulation extends Frame
                           implements Observer,
                                      Runnable {

    private transient BufferedImage img;
   
    /**
     * Die VersionsUID.
     */
    private static final long serialVersionUID = -2260012518107957607L;

    /**
     * Ob der Rahmen der freien Pixel bereits berechnet ist (Wert) oder nicht
     * (null).
     */
    private Vector2D rahmenLinksOben = null;

    /**
     * Ob der Rahmen der freien Pixel bereits berechnet ist (Wert) oder nicht
     * (null).
     */
    private Vector2D rahmenRechtsUnten = null;

    /**
     * Das Feld in seiner tatsächlichen Darstellungsgröße.
     */
    private byte[][] darFeld;

    /**
     * Die Pixel, die noch in der Darstellung gesetzt werden müssen.
     */
    private LinkedList<Pixel2D_08Bit> wartPixel2D;

    /**
     * Die noch nicht in die Darstellung eingefügten NormPixel.
     */
    private LinkedList<Pixel2D_08Bit> neueNormPixel2D;
   
    /**
     * Der Taktgeber für die Darstellung.
     */
    private SimulationsZeit simZ;
   
    /**
     * Das Steuerfenster, das zu dieser Umgebung gehört.
     */
    private SteuerFenster eltFenst;

    /**
     * Die beobachtete Umgebung.
     */
    private Umgebung umgebung;
   
    /**
     * Der ParCollection.
     */
    private ParCollection pars;

    /**
     * Die Breite des Fensters.
     */
    private int breite;

    /**
     * Die Höhe des Fensters.
     */
    private int hoehe;

    /**
     * Der linke Rand.
     */
    private double xRand;

    /**
     * Der rechte Rand.
     */
    private double yRand;

    /**
     * Gibt an, ob beim nächsten repaint() das gesamte Feld (und nicht nur
     * die anstehenden neuen Pixel) neu gezeichnet werden soll.
     */
    private boolean allesNeuZeichnen = false;
   
    /**
     * Das Fenster, in dem die Sensoren dargestellt werden.
     */
    private SensorenDarstellung sensFenster;

    /**
     * Ob die Darstellung weiter aktualisiert werden soll.
     */
    private boolean weiterlaufen;
   
    /**
     * Der Thread, in dem die GUI zur Darstellung der Simulationsumgebung
     * läuft.
     */
    private Thread guiThread;
   
    /**
     * Gibt an, ob die Zeichensession beendet ist und die aktuellen Pixel
     * gezeichnet werden können.
     */
    private boolean zeichnenErlaubt;
   
    /**
     * Der Eltern-Tracebetrachter.
     */
    private TraceBetrachter eltTraceB;
   
    /**
     * Initialisiert das Objekt mit einem Tracebetrachter als Elternfenster.
     *
     * @param fensterText  Der Anzuzeigende Text im Titel des
     *                     Simulationsfensters.
     * @param sensFenst    Das Fenster, in dem die Sensoren dargestellt werden
     *                     (optional).
     * @param elt          Das Eltern-Tracebetrachter-Fenster.
     * @param params       Die Parameter.
     */
    public GuiSimulation(
            final String               fensterText,
            final SensorenDarstellung  sensFenst,
            final TraceBetrachter      elt,
            final ParCollection        params,
            final XMLAufnLesen         aufnahme) {
        this(
                fensterText,
                sensFenst,
                (SteuerFenster) null,
                params,
                aufnahme);
       
        this.eltTraceB = elt;
    }
   
    /**
     * Der Konstruktor. Initialisiert das Objekt mit einem Steuerfenster als
     *                  Elternfenster.
     *
     * @param fensterText  Der Anzuzeigende Text im Titel des
     *                     Simulationsfensters.
     * @param sensFenst    Das Fenster, in dem die Sensoren dargestellt werden
     *                     (optional).
     * @param elt          Das Eltern-Steuerfenster.
     * @param params       Die Parameter.
     */
    public GuiSimulation(
            final String               fensterText,
            final SensorenDarstellung  sensFenst,
            final SteuerFenster        elt,
            final ParCollection        params,
            final XMLAufnLesen         aufnahme) {

        super(fensterText);

       
       
        this.setResizable(false);
        this.pars = params;
        this.zeichnenErlaubt = true;
       
        int breit = aufnahme.getInputField().length
                    + ConstantsSimulation.SIM_RAND_LINKS
                    + ConstantsSimulation.SIM_RAND_RECHTS
                    + 0;
       
        int hoch = aufnahme.getInputField()[0].length
                   + ConstantsSimulation.SIM_RAND_OBEN
                   + ConstantsSimulation.SIM_RAND_UNTEN
                   + 25;
       
       
        this.darFeld = new byte[aufnahme.getInputField().length]
                               [aufnahme.getInputField()[0].length];
       
        this.guiThread = null;
        this.wartPixel2D = new LinkedList<Pixel2D_08Bit>();
        this.neueNormPixel2D = new LinkedList<Pixel2D_08Bit>();
        this.eltFenst = elt;
        this.weiterlaufen = false;
        this.breite   = breit;
        this.hoehe    = hoch;
       
        this.setSize(this.breite, this.hoehe);
        img = new BufferedImage(this.breite, this.hoehe, BufferedImage.TYPE_INT_ARGB);
        this.feldGrAnpass();
        this.setAlwaysOnTop(true);
       
        if (this.eltFenst != null) {
            this.addWindowListener(new WindowClosingAdapter2(false,
                                                             this.eltFenst,
                                                             this));
        }

        this.addComponentListener(
            new ComponentAdapter() {
                @Override
                public void componentResized(final ComponentEvent event) {
                    GuiSimulation.this.breite
                        = GuiSimulation.this.getSize().width;
                    GuiSimulation.this.hoehe
                        = GuiSimulation.this.getSize().height;
                    GuiSimulation.this.allesNeuZeichnen = true;
                    GuiSimulation.this.feldGrAnpass();
                }
            }
        );

        this.addMouseListener(
            new MouseAdapter() {
                @Override
                public void mousePressed(final MouseEvent event) {
                    int x = event.getX();
                    int y = event.getY();

                    if (event.getButton() == 1) {
                        GuiSimulation.this.deselektiereAlle();
                        if (event.getClickCount() <= 1) {
                            Roboter r
                                = GuiSimulation.this.holeNahenDar(x, y, null);
                            r.setSelektiert(true);
                           
                            if (GuiSimulation.this.eltFenst != null) {

                            } else if (GuiSimulation.this.eltTraceB != null) {
                                GuiSimulation.this.eltTraceB.selGraph(r);
                            }
                            StaticMethods.log(
                                    StaticMethods.LOG_INFO,
                                    "Selektiert ("
                                        + r.getId()
                                        + " ["
                                        + r.getFitString()
                                        + "]"
                                        + ").",
                                    GuiSimulation.this.pars);
                           
                            StaticMethods.log(
                                    StaticMethods.LOG_DEBUG,
                                    "TransCode: " + r.getTransCodes()[0] + ".",
                                    GuiSimulation.this.pars);
                            StaticMethods.log(
                                    StaticMethods.LOG_DEBUG,
                                    "VerhCode:  " + r.getVerhCodes()[0] + ".",
                                    GuiSimulation.this.pars);
                        }
                       
                        GuiSimulation.this.allesNeuZeichnen = true;
//                        if (GuiSimulation.this.pars.getVerzoeg().longValue()
//                                > 2000
//                            && GuiSimulation.this.eltFenst != null) {
//                            GuiSimulation.this.pars.setVerzoegerung(2000);
//                        }
                       
                        if (!GuiSimulation.this.weiterlaufen) {
                            GuiSimulation.this.zeichnenErlaubt = true;
                            GuiSimulation.this.neuZeichnen();
                        }
                    } else {
//                        int modus = GuiSimulation.this.pars.getAnzModus();
//                        modus++;
//                        modus %= 3;
//                        GuiSimulation.this.pars.setAnzModus(modus);
                    }
                }
            }
        );

        this.setVisible(true);

        if (sensFenst != null) {
            this.sensFenster = sensFenst;
            this.sensFenster.setLocation(this.getLocation().x + this.getWidth(),
                            this.getLocation().y);
            this.sensFenster.setVisible(true);
            this.setSensorFenster();
        }
    }

    /**
     * Setzt das Sensorfenster (das Fenster, in dem während der Simulation
     * die Sensorwerte angezeigt werden).
     */
    public void setSensorFenster() {

    }
   
    /**
     * @return Returns the breite.
     */
    public int getBreite() {
        return this.breite;
    }

    /**
     * @param breit  The breite to set.
     */
    public void setBreite(final int breit) {
        this.breite = breit;
    }

    /**
     * @return Returns the hoehe.
     */
    public int getHoehe() {
        return this.hoehe;
    }

    /**
     * @param hoeh  The hoehe to set.
     */
    public void setHoehe(final int hoeh) {
        this.hoehe = hoeh;
    }

    /**
     * Passt die Größe der Darstellung des simulierten Feldes der Größe
     * des Fensters von <code>this</code> an.
     */
    private void feldGrAnpass() {
        this.setzeDarAusdehnung(this.breite
                                    - ConstantsSimulation.SIM_RAND_LINKS
                                    - ConstantsSimulation.SIM_RAND_RECHTS,
                                this.hoehe
                                    - ConstantsSimulation.SIM_RAND_OBEN
                                    - ConstantsSimulation.SIM_RAND_UNTEN
                                    - 25);
    }

    /**
     * Deselektiert alle RobEA in der Liste der Akteure der Umgebung.
     */
    private void deselektiereAlle() {
        Iterator<Roboter> it = this.umgebung.getAgenten().iterator();
        Roboter rob;
        while (it.hasNext()) {
            rob = it.next();
            rob.setSelektiert(false);
        }
        if (this.eltTraceB != null) {
            this.eltTraceB.deselektiereAlle();
        }
    }
   
    /**
     * Setzt die Ausdehnung der tatsächlichen Darstellungsgröße des Feldes.
     * Beachte: Nach einem Neusetzen der Ausdehnung muss das ganze Bild einmal
     * neu gezeichnet werden.
     *
     * @param x  X-Richtung der tatsächlichen Ausdehnung des Feldes.
     * @param y  Y-Richtung der tatsächlichen Ausdehnung des Feldes.
     */
    public void setzeDarAusdehnung(final int x,
                                   final int y) {
        this.darFeld = new byte[x][y];
        this.rahmenLinksOben = null;
        this.rahmenRechtsUnten = null;
    }

    /**
     * Berechnet den Rahmen des Darstellungsfeldes:
     *
     * Rechteckiger Rahmen, der alle Pixel umfasst, die auf dem
     * Darstellungsfeld nicht auf eine Rahmenfarbe gesetzt sind und der
     * kleinste aller solcher Rahmen ist.
     */
    private void berechneRahmen() {
        double minX = Double.MAX_VALUE;
        double minY = Double.MAX_VALUE;
        double maxX = 0;
        double maxY = 0;
       
        for (int i = 0; i < this.darFeld.length; i++) {
            for (int j = 0; j < this.darFeld[0].length; j++) {
                if (this.darFeld[i][j] != ConstantsSimulation.FARBE_RAHMEN) {
                    if (i < minX) {
                        minX = i;
                    }
                    if (i > maxX) {
                        maxX = i;
                    }
                    if (j < minY) {
                        minY = j;
                    }
                    if (j > maxY) {
                        maxY = j;
                    }
                }
            }
        }
       
        this.rahmenLinksOben = new Vector2D(minX, minY);
        this.rahmenRechtsUnten = new Vector2D(maxX, maxY);
    }
   
    /**
     * Gibt die linke obere Ecke eines rechteckigen Rahmens zurück, der alle
     * Pixel umfasst, die auf dem Darstellungsfeld nicht auf eine Rahmenfarbe
     * gesetzt sind und der kleinste aller solcher Rahmen ist.
     *
     * @return  Die linke obere Ecke des nicht-gesetzt-Rahmens.
     */
    public Vector2D getLinksOben() {
        if (this.rahmenLinksOben == null) {
            this.berechneRahmen();
        }
       
        return this.rahmenLinksOben;
    }

    /**
     * Gibt die rechte untere Ecke eines rechteckigen Rahmens zurück, der alle
     * Pixel umfasst, die auf dem Darstellungsfeld nicht auf eine Rahmenfarbe
     * gesetzt sind und der kleinste aller solcher Rahmen ist.
     *
     * @return  Die rechte untere Ecke des nicht-gesetzt-Rahmens.
     */
    public Vector2D getRechtsUnten() {       
        if (this.rahmenRechtsUnten == null) {
            this.berechneRahmen();
        }
       
        return this.rahmenRechtsUnten;
    }

    /**
     * Berechnet die Pixel, die sich in der DARSTELLUNG seit der letzten
     * Aktualisierung verändert haben und in die Grafik eingezeichnet werden
     * müssen.
     */
    private void berZuZeichnendePixel() {
        if (this.umgebung == null) {
            // Zeichnen vor Initialisierung angefordert.
            return;
        }
       
        double aF = this.ausdDarX();
        double bF = this.ausdDarY();
        double af = this.umgebung.ausdX();
        double bf = this.umgebung.ausdY();
        double xFakt = aF / af;
        double yFakt = bF / bf;
        int xNeuErst;
        int yNeuErst;
        int xNeuLetzt;
        int yNeuLetzt;
        Pixel2D_08Bit normPix = null;
        Iterator<Pixel2D_08Bit> it = this.neueNormPixel2D.iterator();

        while (it.hasNext()) {
            try {
                normPix = it.next();
                xNeuErst = (int) Math.round(normPix.x * xFakt);
                yNeuErst = (int) Math.round(normPix.y * yFakt);
                xNeuLetzt = (int) Math.round((normPix.x + 1) * xFakt);
                yNeuLetzt = (int) Math.round((normPix.y + 1) * yFakt);
                for (int x = xNeuErst; x < xNeuLetzt; x++) {
                    for (int y = yNeuErst; y < yNeuLetzt; y++) {
                        if (this.darFeld[x][y] != normPix.color()) {
                            this.wartPixel2D.add(new Pixel2D_08Bit(x,
                                                         y,
                                                         normPix.color()));
                            this.darFeld[x][y] = normPix.color();
                        }
                    }
                }
            } catch (final Exception e) {
                StaticMethods.log(StaticMethods.LOG_WARNING,
                              "Norm-Pixel-Liste wurde unerlaubt modifiziert.",
                              this.pars);
                it = this.neueNormPixel2D.iterator();
            }
        }
       
        this.neueNormPixel2D.clear();
    }

    /**
     * Gibt die Ausdehnung des Darstellungs-Feldes in X-Richtung zurück.
     *
     * @return  Die Ausdehnung des Darstellungs-Feldes in X-Richtung.
     */
    public int ausdDarX() {
        return this.darFeld.length;
    }

    /**
     * Gibt die Ausdehnung des Darstellungs-Feldes in Y-Richtung zurück.
     *
     * @return  Die Ausdehnung des Darstellungs-Feldes in Y-Richtung.
     */
    public int ausdDarY() {
        return this.darFeld[0].length;
    }

    /**
     * Gibt den RobEA zurück, der sich am nächsten zum
     * angegebenen Punkt befindet. Die Koordinate bezieht sich dabei auf das
     * DARSTELLUNGSfeld.
     *
     * @param x  X-Koordinate
     * @param y  Y-Koordinate
     * @param nicht  Welche RobEA nicht zurückgegeben werden sollen.
     *
     * @return  Der RobEA, der sich im Darstellungsfeld am nächsten zu der
     *          Koordinate befindet.
     */
    public Roboter holeNahenDar(
            final int     x,
            final int     y,
            final HashSet<Roboter> nicht) {
        final double xx = x;
        final double yy = y;
        double normX;
        double normY;
        HashSet<Roboter> nichtBeachten;
       
        if (nicht == null) {
            nichtBeachten = new HashSet<Roboter>();
        } else {
            nichtBeachten = nicht;
        }
       
        normX = xx * this.umgebung.ausdX() / this.ausdDarX();
        normY = yy * this.umgebung.ausdY() / this.ausdDarY();
        normX = normX - ConstantsSimulation.SIM_RAND_LINKS;
        normY = normY - ConstantsSimulation.SIM_RAND_OBEN - 25;

        return this.umgebung.holeNahenNorm((int) normX,
                                           (int) normY,
                                           nichtBeachten);
    }

    /**
     * Zeichnet das Feld neu.
     *
     * @param g  Das Grafik-Objekt.
     */
    @Override
    public void paint(final Graphics g) {
        super.paint(g);
        this.maleFeld(g);
    }

    /**
     * Zeichnet die aktuellen änderungen am Feld auf den Bildschirm.
     *
     * @param g  Das Grafik-Feld.
     */
    private void maleFeld(final Graphics g) {
        Graphics g2 = img.getGraphics();
        LinkedList<Pixel2D_08Bit> pixel2D;
        Pixel2D_08Bit aktPix;
        Iterator<Pixel2D_08Bit> it;
       
        if (this.xRand == 0 && this.yRand == 0) {
            this.xRand = g.getClipBounds().getX()
                         + ConstantsSimulation.SIM_RAND_LINKS;
            this.yRand = g.getClipBounds().getY()
                         + ConstantsSimulation.SIM_RAND_OBEN;
        }

        this.berZuZeichnendePixel();
       
        pixel2D = this.wartPixel2D;

        it = pixel2D.iterator();
        while (it.hasNext()) {
            aktPix = it.next();

            if (aktPix.color() == ConstantsSimulation.FARBE_ROB) {
                g2.setColor(ConstantsSimulation.C_VORDERGRUND);
            } else if (aktPix.color() == ConstantsSimulation.FARBE_SEL) {
                g2.setColor(ConstantsSimulation.C_SPEZIAL);
            } else if (aktPix.color() == ConstantsSimulation.FARBE_RAHMEN) {
                g2.setColor(ConstantsSimulation.C_RAHMEN);
            } else if (aktPix.color() == ConstantsSimulation.FARBE_GGSTD) {
                g2.setColor(ConstantsSimulation.C_GEGENSTAND);
            } else if (aktPix.color() >= 100 && aktPix.color() <= 125) {
                // Benutzerfarben.
                g2.setColor(ConstantsSimulation.C_BENUTZER[aktPix.color() - 100]);
            } else if (aktPix.color() == ConstantsSimulation.FARBE_DURCHLAESSIG) {
                g2.setColor(ConstantsSimulation.C_DURCHLAESSIG);
            } else {
                g2.setColor(this.getBackground());
            }

            /*
            g.drawRect((int) (aktPix.x + this.xRand),
                       (int) (aktPix.y + this.yRand),
                       0,
                       0);
                    */
            g2.drawRect((int) (aktPix.x + this.xRand),
                    (int) (aktPix.y + this.yRand),
                    0,
                    0);
            //img.setRGB(x, y, makeRGBA(0, r, 0, 255));

        }
        pixel2D.clear();
        g.drawImage(img, 0, 0, this);
    }

    /**
     * überladen der update-Methode ohne Löschen des aktuellen Bildes.
     *
     * @param g  Das Graphics-Objekt.
     */
    @Override
    public void update(final Graphics g) {
        this.paint(g);
    }
   
    /**
     * St��t das Neuzeichnen zum nächstmöglichen Zeitpunkt über
     * <code>repaint</code> an.
     */
    private void neuZeichnen() {
        if (this.allesNeuZeichnen) {
            this.umgebung.alleFelderNeu();
        }
        this.repaint();
        this.allesNeuZeichnen = false;
    }

    /**
     * Die RUN-Methode des Threads.
     */
    @Override
    public void run() {
       
    }
   
    /**
     * Beendet diesen Lauf.
     */
    public void simBeenden() {
        if (this.weiterlaufen) {
            this.weiterlaufen = false;
           
            this.simZ.zeitBeenden();
            this.simZ.reset();

            if (this.pars.getParValueBoolean(eas.statistics.ConstantsStatistics.EINFACHE_DARSTELLUNG)) {
                this.pars.setParValue(eas.statistics.ConstantsStatistics.BEZIER_KONST,
                        eas.startSetup.marbBuilder.zeichenModi.ConstantsZeichenModi.BEZ_FANCY);
            } else {
                this.pars.setParValue(eas.statistics.ConstantsStatistics.BEZIER_KONST,
                        eas.startSetup.marbBuilder.zeichenModi.ConstantsZeichenModi.BEZ_NORMAL);
            }
        }
    }
   
    /**
     * Startet die Darstellung einer Simulation.
     */
    public void simStarten() {
        this.weiterlaufen = true;
        this.guiThread = new Thread(this);
        this.guiThread.start();
    }
   
    /**
     * @param takt  Die Simulationszeit.
     */
    public void registriereTakt(final SimulationsZeit takt) {
        this.simZ = takt;
    }

    /**
     * Die vom Interface geforderte Methode zum Reagieren auf änderungen am
     * beobachteten Objekt.
     *
     * @param o    Das Observierte Objekt.
     * @param arg  Wei� der Himmel.
     */
    @Override
    public void update(
            final Observable o,
            final Object arg) {

        if (this.umgebung == null && o.getClass() == Umgebung.class) {
            this.umgebung = (Umgebung) o;
        }
       
        if (this.umgebung.getNeuerPixel2D() == null) {
            this.setzeSensoren();
            this.zeichnenErlaubt = true;
            if (this.eltFenst == null && this.zeichnenErlaubt) {
                this.neuZeichnen();
                this.zeichnenErlaubt = false;
            }
        } else {
            this.neueNormPixel2D.add(this.umgebung.getNeuerPixel2D());
            this.zeichnenErlaubt = false;
        }
    }
   
    /**
     * Gibt alle zu zeichnenden Pixel zurück.
     *
     * @return  Alle zu zeichnenden Pixel.
     */
    public LinkedList<Pixel2D_08Bit> allePixel2D() {
        this.umgebung.alleFelderNeu();
        this.berZuZeichnendePixel();
        return this.wartPixel2D;
    }
   
    /**
     * Setzt die aktuell berechneten Sensoren in das Sensorfenster ein
     * und (TODO!) setzt die im Sensorfenster eingetragenen Sensoren als
     * Konstante Sensoren für den RobEA.
     */
    private void setzeSensoren() {

    }

    /**
     * Leert das Feld und löscht es in der Darstellung.
     */
    public void loescheFeld() {
        this.umgebung.leereFeld();
        this.umgebung.beendeZeichenSession();
    }
   
    /**
     * @return Returns the umgebung.
     */
    public Umgebung getUmgeb() {
        return this.umgebung;
    }

    /**
     * @param weiter  The weiterlaufen to set.
     */
    public void setWeiterlaufen(final boolean weiter) {
        this.weiterlaufen = weiter;
    }
}
TOP

Related Classes of eas.startSetup.marbBuilder.traceBetrachter.GuiSimulation

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.