Einige Bugfixes und Verbesserungen und ganz viel Doku

This commit is contained in:
ngb
2022-11-29 10:12:04 +01:00
parent 47827683e8
commit 080db1f431
11 changed files with 613 additions and 89 deletions

View File

@@ -112,7 +112,7 @@ public class Color implements Paint {
}
/**
* Erstellt eine graue Farbe entsprechend des Grauwertes <var>gray</var>.
* Erstellt eine graue Farbe entsprechend dem Grauwert {@code gray}.
*
* @param gray Ein Grauwert zwischen 0 und 255.
*/
@@ -121,8 +121,8 @@ public class Color implements Paint {
}
/**
* Erstellt eine graue Farbe entsprechend des Grauwertes <var>gray</var> und
* des Transparentwertes <var>alpha</var>.
* Erstellt eine graue Farbe entsprechend dem Grauwert {@code gray} und dem
* Transparenzwert {@code alpha}.
*
* @param gray Ein Grauwert zwischen 0 und 255.
*/
@@ -131,9 +131,9 @@ public class Color implements Paint {
}
/**
* Erstellt eine Farbe. Die Parameter <var>red</var>, <var>green</var> und
* <var>blue</var> geben die Rot-, Grün- und Blauanteile der Farbe. Die
* Werte liegen zwischen 0 und 255.
* Erstellt eine Farbe. Die Parameter {@code red}, {@code green} und
* {@code blue} geben die Rot-, Grün- und Blauanteile der Farbe. Die Werte
* liegen zwischen 0 und 255.
*
* @param red Rotwert zwischen 0 und 255.
* @param green Grünwert zwischen 0 und 255.
@@ -144,11 +144,11 @@ public class Color implements Paint {
}
/**
* Erstellt eine Farbe. Die Parameter <var>red</var>, <var>green</var> und
* <var>blue</var> geben die Rot-, Grün- und Blauanteile der Farbe. Die
* Werte liegen zwischen 0 und 255.
* <var>alpha</var> gibt den den Transparentwert an (auch zwischen
* 0 und 255), wobei 0 komplett durchsichtig ist und 255 komplett deckend.
* Erstellt eine Farbe. Die Parameter {@code red}, {@code green} und
* {@code blue} geben die Rot-, Grün- und Blauanteile der Farbe. Die Werte
* liegen zwischen 0 und 255. {@code alpha} gibt den den Transparentwert an
* (auch zwischen 0 und 255), wobei 0 komplett durchsichtig ist und 255
* komplett deckend.
*
* @param red Rotwert zwischen 0 und 255.
* @param green Grünwert zwischen 0 und 255.
@@ -160,20 +160,20 @@ public class Color implements Paint {
}
/**
* Erstellt eine Farbe als Kopie von <var>color</var>.
* Erstellt eine Farbe als Kopie von {@code color}.
*
* @param color
* @param color Eine Farbe.
*/
public Color( Color color ) {
this(color.getRGBA(), true);
}
/**
* Erstellt eine Farbe als Kopie von <var>color</var> und ersetzt den
* Transparentwert durch <var>alpha</var>.
* Erstellt eine Farbe als Kopie von {@code color} und ersetzt den
* Transparentwert durch {@code alpha}.
*
* @param color
* @param alpha
* @param color Eine Farbe.
* @param alpha Der neue Transparenzwert.
*/
public Color( Color color, int alpha ) {
this(color.getRed(), color.getGreen(), color.getBlue(), alpha);
@@ -208,18 +208,51 @@ public class Color implements Paint {
/**
* Erzeugt eine Farbe aus einem kodierten RGBA Integer-Wert.
* <p>
* Der 32-bit Integer enthält (von rechts) in Bit 1 bis 8 den Rotwert, in
* Bit 9 bis 16 Grünwert, in Bit 17 bis 24 den Blauwert und in Bit 25 bis 32
* den Transparenzwert der Farbe.
*
* @param rgba
* @return
* @param rgba Eine RGBA-Farbe.
* @return Ein Farbobjekt.
*/
public static Color getRGBColor( int rgba ) {
return new Color(rgba, true);
}
/**
* Erzeugt eine Farbe aus Werten im
* <a href="https://de.wikipedia.org/wiki/HSV-Farbraum">HSB-Farbraum</a>.
* <p>
* {code h} beschreibt den Farbwert (engl. <em>hue</em>), {@code s} die
* Sättigung (engl. <em>saturation</em>) und {@code b} die absolute
* Helligkeit (engl. <em>brightness</em>) der Farbe. Alle Werte werden
* zwischen 0.0 und 1.0 angegeben.
*
* @param h Der Farbwert.
* @param s Die Sättigung.
* @param b Die absolute Helligkeit.
* @return Ein Farbobjekt.
* @see java.awt.Color#getHSBColor(float, float, float)
*/
public static Color getHSBColor( double h, double s, double b ) {
return new Color(java.awt.Color.getHSBColor((float) h, (float) s, (float) b));
}
/**
* Erzeugt eine Farbe aus Werten im
* <a href="https://de.wikipedia.org/wiki/HSV-Farbraum">HSL-Farbraum</a>.
* <p>
* {code h} beschreibt den Farbwert (engl. <em>hue</em>), {@code s} die
* Sättigung (engl. <em>saturation</em>) und {@code l} die relative
* Helligkeit (engl. <em>lightness</em>) der Farbe. Alle Werte werden
* zwischen 0.0 und 1.0 angegeben.
*
* @param h Der Farbwert.
* @param s Die Sättigung.
* @param l Die relative Helligkeit.
* @return Ein Farbobjekt.
*/
public static Color getHSLColor( double h, double s, double l ) {
int rgb = Color.HSLtoRGB(new float[]{(float) h, (float) s, (float) l});
return Color.getRGBColor(rgb);
@@ -259,12 +292,16 @@ public class Color implements Paint {
}
/**
* Erzeugt eine Farbe aus einem hexadezimalen Code. Der Hexcode kann sechs-
* oder achtstellig sein (wenn ein Transparentwert vorhanden ist). Dem Code
* kann ein {@code #} Zeichen vorangestellt sein.
* Erzeugt eine Farbe aus einem hexadezimalen Code. Der Hexcode kann drei-,
* sechs- oder achtstellig sein (wenn ein Transparentwert vorhanden ist).
* Dem Code kann ein {@code #} Zeichen vorangestellt sein, muss es aber
* nicht.
* <p>
* Bei einem dreistelligen Code wird jedes zeichen doppelt interpretiert.
* Das beduetet {@code #ABC} ist gleichbedeutend mit {@code #AABBCC}.
*
* @param hexcode
* @return
* @param hexcode Eine Farbe als Hexcode.
* @return Ein Farbobjekt.
*/
public static Color parseHexcode( String hexcode ) {
if( hexcode.startsWith("#") ) {
@@ -301,7 +338,7 @@ public class Color implements Paint {
if( color1 == null && color2 == null ) {
throw new IllegalArgumentException("Color.interpolate() needs at least one color to be not null.");
}
if( t < 0.0 || color2 == null ) {
if( (color1 != null && t < 0.0) || color2 == null ) {
return color1.copy();
}
if( t > 1.0 || color1 == null ) {
@@ -351,6 +388,14 @@ public class Color implements Paint {
return hsl;
}
/**
* Konvertiert die Komponenten einer Farbe aus dem HSL-Farbraum in den
* RGB-Farbraum.
*
* @param hsl Die HSL-Komponenten als float-Array.
* @return Der RGBA-Farbwert.
* @see #HSLtoRGB(float[], int)
*/
public static int HSLtoRGB( float[] hsl ) {
return HSLtoRGB(hsl, 255);
}
@@ -359,9 +404,9 @@ public class Color implements Paint {
* Konvertiert eine Farbe mit Komponenten im HSL-Farbraum in den
* RGB-Farbraum.
* <p>
* Die Farbkomponenten werden als Float-Array übergeben. Im Index 0 steht
* der h-Wert im Bereich 0 bis 360, Index 1 und 2 enthalten den s- und
* l-Wert im Bereich von 0 bis 1.
* Die Farbkomponenten werden als float-Array übergeben. Im Index 0 steht
* der H-Wert im Bereich 0 bis 360, Index 1 und 2 enthalten den S- und
* L-Wert im Bereich von 0 bis 1.
*
* @param hsl Die Farbkomponenten im HSL-Farbraum.
* @param alpha Ein Transparenzwert im Bereich 0 bis 255.
@@ -506,10 +551,11 @@ public class Color implements Paint {
/**
* Prüft, ob ein anderes Objekt zu diesem gleich ist.
* <p>
* Die Methode gibt genau dann {@code true} zurück, wenn das andere Objekt
* nicht {@code null} ist, vom Typ {@code Color} ist und es dieselben Rot-,
* Grün-, Blau- und Transparenzwerte hat.
*
* Die Methode gibt genau dann {@code true} zurück, wenn das andere
* Objekt nicht {@code null} ist, vom Typ {@code Color} ist und es
* dieselben Rot-, Grün-, Blau- und Transparenzwerte hat.
* @param obj Das zu vergleichende Objekt.
* @return {@code true}, wenn die Objekte gleich sind, sonst {@code false}.
*/

View File

@@ -1054,7 +1054,7 @@ public class Constants {
}
/**
* Ermittelt den Arkuskosinus der angegebenen Zahl.
* Ermittelt den Arcuskosinus der angegebenen Zahl.
*
* @param x Eine Zahl.
* @return {@code acos(x)}.
@@ -1064,7 +1064,7 @@ public class Constants {
}
/**
* Ermittelt den Arkusktangens der angegebenen Zahl.
* Ermittelt den Arcusktangens der angegebenen Zahl.
*
* @param x Eine Zahl.
* @return {@code atan(x)}.
@@ -1681,38 +1681,93 @@ public class Constants {
}
}
/**
* Konvertiert einen char-Wert in einen double-Wert.
*
* @param value Der char-Wert.
* @return Ein double-Wert.
*/
public static final double asDouble( char value ) {
return value;
}
/**
* Konvertiert einen byte-Wert in einen double-Wert.
*
* @param value Der byte-Wert.
* @return Ein double-Wert.
*/
public static final double asDouble( byte value ) {
return value;
}
/**
* Konvertiert einen short-Wert in einen double-Wert.
*
* @param value Der short-Wert.
* @return Ein double-Wert.
*/
public static final double asDouble( short value ) {
return value;
}
/**
* Konvertiert einen long-Wert in einen double-Wert.
*
* @param value Der long-Wert.
* @return Ein double-Wert.
*/
public static final double asDouble( long value ) {
return (double) value;
}
/**
* Konvertiert einen double-Wert in einen double-Wert.
*
* @param value Der double-Wert.
* @return Ein double-Wert.
*/
public static final double asDouble( double value ) {
return value;
}
/**
* Konvertiert einen float-Wert in einen double-Wert.
*
* @param value Der float-Wert.
* @return Ein double-Wert.
*/
public static final double asDouble( float value ) {
return value;
}
/**
* Konvertiert einen int-Wert in einen double-Wert.
*
* @param value Der int-Wert.
* @return Ein double-Wert.
*/
public static final double asDouble( int value ) {
return value;
}
/**
* Konvertiert einen boolean-Wert in einen double-Wert.
*
* @param value Der boolean-Wert.
* @return Ein double-Wert.
*/
public static final double asDouble( boolean value ) {
return value ? 1.0 : 0.0;
}
/**
* Konvertiert einen String in einen double-Wert.
*
* @param value Der String.
* @return Ein double-Wert.
* @see Double#parseDouble(String)
*/
public static final double asDouble( String value ) {
try {
return Double.parseDouble(value);
@@ -1721,38 +1776,93 @@ public class Constants {
}
}
/**
* Konvertiert einen char-Wert in einen boolean-Wert.
*
* @param value Der char-Wert.
* @return Ein boolean-Wert.
*/
public static final boolean asBool( char value ) {
return value != 0;
}
/**
* Konvertiert einen byte-Wert in einen boolean-Wert.
*
* @param value Der byte-Wert.
* @return Ein boolean-Wert.
*/
public static final boolean asBool( byte value ) {
return value != 0;
}
/**
* Konvertiert einen short-Wert in einen boolean-Wert.
*
* @param value Der short-Wert.
* @return Ein boolean-Wert.
*/
public static final boolean asBool( short value ) {
return value != 0;
}
/**
* Konvertiert einen int-Wert in einen boolean-Wert.
*
* @param value Der int-Wert.
* @return Ein boolean-Wert.
*/
public static final boolean asBool( int value ) {
return value != 0;
}
/**
* Konvertiert einen long-Wert in einen boolean-Wert.
*
* @param value Der long-Wert.
* @return Ein boolean-Wert.
*/
public static final boolean asBool( long value ) {
return value != 0L;
}
/**
* Konvertiert einen double-Wert in einen boolean-Wert.
*
* @param value Der double-Wert.
* @return Ein boolean-Wert.
*/
public static final boolean asBool( double value ) {
return value != 0.0;
}
/**
* Konvertiert einen float-Wert in einen boolean-Wert.
*
* @param value Der float-Wert.
* @return Ein boolean-Wert.
*/
public static final boolean asBool( float value ) {
return value != 0.0f;
}
/**
* Konvertiert einen boolean-Wert in einen boolean-Wert.
*
* @param value Der boolean-Wert.
* @return Ein boolean-Wert.
*/
public static final boolean asBool( boolean value ) {
return value;
}
/**
* Konvertiert einen String in einen boolean-Wert.
*
* @param value Der String.
* @return Ein boolean-Wert.
* @see Boolean#parseBoolean(String)
*/
public static final boolean asBool( String value ) {
return Boolean.parseBoolean(value);
}
@@ -1813,7 +1923,7 @@ public class Constants {
return Integer.valueOf(binary, 16);
}
// Konstants für Key events (Copied from KeyEvent)
// Konstanten für Key events (Copied from KeyEvent)
/**
* Constant for the ENTER virtual key.

View File

@@ -12,10 +12,10 @@ import java.awt.image.BufferedImage;
* Die {@code Zeichenleinwand} besteht aus einer Reihe von Ebenen, die
* übereinandergelegt und von "unten" nach "oben" gezeichnet werden. Die Inhalte
* der oberen Ebenen können also Inhalte der darunterliegenden verdecken.
*
* Ebenen sind ein zentraler Bestandteil bei der Implementierung einer {@link Zeichenmaschine}.
* Es werden
* Sie erben von {@code Constants}, damit sie beim
* <p>
* Ebenen sind ein zentraler Bestandteil bei der Implementierung einer
* {@link Zeichenmaschine}. Sie erben von {@code Constants}, da neue Ebenentypen
* von Nutzern implementiert werden können.
*/
public abstract class Layer extends Constants implements Drawable, Updatable {
@@ -43,24 +43,39 @@ public abstract class Layer extends Constants implements Drawable, Updatable {
protected boolean active = true;
/**
* Erstellt eine neue Ebene mit den Standardmaßen.
*/
public Layer() {
this(DEFAULT_WIDTH, DEFAULT_HEIGHT);
}
/**
* Erstellt eine neue Ebene mit den angegebenen Maßen.
*
* @param width Die Breite der Ebene.
* @param height Die Höhe der Ebene.
*/
public Layer( int width, int height ) {
createCanvas(width, height);
}
/**
* @return Die Breite der Ebene.
*/
public int getWidth() {
return buffer.getWidth();
}
/**
* @return Die Höhe der Ebene.
*/
public int getHeight() {
return buffer.getHeight();
}
/**
* Ändert die Größe der Ebene auf die angegebene Größe.
* Ändert die Größe der Ebene auf die angegebenen Maße.
*
* @param width Die neue Breite.
* @param height Die neue Höhe.
@@ -88,7 +103,7 @@ public abstract class Layer extends Constants implements Drawable, Updatable {
/**
* Erstellt einen neuen Puffer für die Ebene und konfiguriert diesen.
*
* @param width Width des neuen Puffers.
* @param width Breite des neuen Puffers.
* @param height Höhe des neuen Puffers.
*/
private void createCanvas( int width, int height ) {
@@ -115,7 +130,7 @@ public abstract class Layer extends Constants implements Drawable, Updatable {
* Erstellt einen neuen Puffer für die Ebene mit der angegebenen Größe und
* kopiert den Inhalt des alten Puffers in den Neuen.
*
* @param width Width des neuen Puffers.
* @param width Breite des neuen Puffers.
* @param height Höhe des neuen Puffers.
*/
private void recreateCanvas( int width, int height ) {
@@ -155,14 +170,26 @@ public abstract class Layer extends Constants implements Drawable, Updatable {
return visible;
}
/**
* Versteckt die Ebene.
*/
public void hide() {
visible = false;
}
public void view() {
/**
* Zeigt die Ebene an, falls sie versteckt war.
*/
@SuppressWarnings("unused")
public void show() {
visible = true;
}
/**
* Versteckt oder zeigt die Ebene, je nachdem, welchen Zustand sie derzeit
* hat.
*/
@SuppressWarnings("unused")
public void toggle() {
visible = !visible;
}

View File

@@ -11,17 +11,71 @@ public final class Options {
private Options() {
}
/**
* Linienstile für Konturlinien.
*/
public enum StrokeType {
SOLID, DASHED, DOTTED
/**
* Durchgezogene Linien.
*/
SOLID,
/**
* Getrichelte Linien.
*/
DASHED,
/**
* Gepunktete Linien.
*/
DOTTED
}
/**
* Stile für Pfeilspitzen.
*/
public enum ArrowHead {
LINES, FILLED
/**
* Einfache Pfeilspitze aus zwei Linien.
*/
LINES,
/**
* Gefülltes Dreieck.
*/
FILLED
}
/**
* Arten von Bögen.
* <p>
* Die Werte legen fest, wie Bögen geschlossen werden sollen, wenn sie
* beispielsweise gefüllt werden.
* <p>
* Wrapper für die AWT-Konstanten in {@link Arc2D}.
*/
public enum PathType {
OPEN(Arc2D.OPEN), CLOSED(Arc2D.CHORD), PIE(Arc2D.PIE);
/**
* Offener Pfad, bei dem die Pfadenden direkt miteinander verbunden
* werden ohne eine Linie zu ziehen.
*/
OPEN(Arc2D.OPEN),
/**
* Geschlossener Pfad, bei dem die Pfadenden direkt miteinander
* verbunden werden, indem eine Linie gezogen wird.
*/
CLOSED(Arc2D.CHORD),
/**
* Geschlossener Pfad, bei dem Linien von den Pfadenden zum Mittelpunkt
* des Kreises, der den Kreisbogen festlegt, gezogen werden.
*/
PIE(Arc2D.PIE);
/**
* Der entsprechende Wert der Konstanten in {@link Arc2D}
*/
public final int awt_type;
PathType( int type ) {
@@ -33,25 +87,100 @@ public final class Options {
* Zustände in denen sich die Zeichenmaschine befinden kann.
*/
public enum AppState {
/**
* Die Zeichenmaschine befindet sich in der Initialisierung. Die
* Laufzeitumgebung wird konfiguriert und alle nötigen Komonenten
* ({@link Zeichenfenster}, {@link Zeichenleinwand}, ...) werden
* erstellt.
*/
INITIALIZING,
/**
* Die Initialisierung der Zeichenmaschine ist beendet, aber der
* {@link schule.ngb.zm.Zeichenmaschine.Zeichenthread Zeichenthread}
* wurde noch nicht gestartet.
*/
INITIALIZED,
/**
* Die Zeichenmaschine wurde gestartet und der
* {@link schule.ngb.zm.Zeichenmaschine.Zeichenthread Zeichenthread}
* arbeitet.
*/
RUNNING,
/**
* Der {@link schule.ngb.zm.Zeichenmaschine.Zeichenthread Zeichenthread}
* wurde pausiert.
*/
PAUSED,
/**
* Der {@link schule.ngb.zm.Zeichenmaschine.Zeichenthread Zeichenthread}
* wurde gestoppt, die Zeichenmaschine ist aber noch nicht vollständig
* heruntergefahren und hat noch nicht alle Ressourcen freigegeben.
*/
STOPPED,
/**
* Der {@link schule.ngb.zm.Zeichenmaschine.Zeichenthread Zeichenthread}
* ist beendet.
*/
TERMINATED,
/**
* Die Zeichenmaschine ist dabei, vollständig herunterzufahren und alle
* Ressourcen freizugeben.
*/
QUITING,
/**
* Der {@link schule.ngb.zm.Zeichenmaschine.Zeichenthread Zeichenthread}
* wartet gerade auf den nächsten Frame.
*/
IDLE,
/**
* Die Zeichenmaschine führt gerade
* {@link Zeichenmaschine#update(double)} aus.
*/
UPDATING,
/**
* Die Zeichenmaschine führt gerade {@link Zeichenmaschine#draw()} aus.
*/
DRAWING,
/**
* Die Ausführung der Zeichenmaschine wurde mit
* {@link Zeichenmaschine#delay(int)} verzögert und wartet auf
* Fortsetzung.
*/
DELAYED,
/**
* Die Zeichenmaschine sendet gereade gesammelte Events und führt Tasks
* aus.
*/
DISPATCHING
}
/**
* Richtungen für die Ausrichtung von Formen. Richtungen sind durch
* Einheitsvektoren bzw. deren Kombination repräsentiert, wodurch mit ihnen
* gerechnet werden kann. Jede Richtung ist zusätzlich als Himmelsrichtung
* definiert.
* Einheitsvektoren bzw. deren Kombination im Koordinatensystem der
* Zeichenfläche repräsentiert, wodurch mit ihnen gerechnet werden kann. Die
* Richtung {@link #DOWN} ist beispielsweise gleich {@code (1, 0)}.
* <p>
* Jede Richtung ist zusätzlich als Himmelsrichtung definiert. {@link #EAST}
* ist äquivalent zu {@link #RIGHT} als {@code (0, 1)} definiert. Auch wenn
* beide Werte dieselbe Richtung beschreiben sind sie nicht "gleich"
* ({@code EAST != RIGHT}). Um verschiedene Richtungen zuverlässig zu
* vergleichen, sollte daher {@link #equals(Direction)} verwendet werden.
* <p>
* Für zusammengesetzten Richtungen wie {@link #NORTHEAST} bzw
* {@link #UPRIGHT} lassen sich mit {@link #in(Direction)} und
* {@link #contains(Direction)} Beziehungen zu den anderen Richtungen
* prüfen. Beispielsweise ist {@code NORTHEAST.contains(NORTH)} wahr.
*/
public enum Direction {
CENTER(0, 0),
@@ -89,31 +218,117 @@ public final class Options {
this.y = original.y;
}
/**
* Prüft, ob die angegebene Richtung gleich dieser ist. Dabei werden die
* Komponenten des Richtungsvektors geprüft. Daher sind für die Methode
* beispielsweise {@link #NORTH} und {@link #UP} gleich.
*
* @param dir Eine andere Richtung.
* @return {@code true}, wenn die Richtungen dieselben Komponenten
* haben, {@code false} sonst.
*/
public boolean equals( Direction dir ) {
return this.x == dir.x && this.y == dir.y;
}
/**
* Prüft, ob diese Richtung Tile der angegebenen Richtung ist.
* <p>
* Beispielsweise ist {@link #NORTH} Teil von {@link #NORTHWEST}, aber
* nicht von {@link #SOUTHWEST}. Dabei wird doe Art der Richtung nicht
* beachtet. {@link #UP} ist daher auch Teil von {@link #NORTHWEST}.
*
* <pre>
* NORTH.in(NORTHWEST) // true
* NORTH.in(SOUTHWEST) // false
* UP.in(NORTHWEST) // true
* </pre>
*
* @param dir Eine andere Richtung.
* @return {@code true}, wenn diese Richtungen Teil der anderen ist,
* {@code false} sonst.
*/
public boolean in( Direction dir ) {
return (this.x == dir.x && this.y == 0) || (this.y == dir.y && this.x == 0) || (this.x == dir.x && this.y == dir.y);
}
/**
* Prüft, ob die angegebene Richtung Teil dieser Richtung ist.
* <p>
* Beispielsweise ist {@link #NORTH} Teil von {@link #NORTHWEST}, aber
* nicht von {@link #SOUTHWEST}. Dabei wird die Art der Richtung nicht
* beachtet. {@link #UP} ist daher auch Teil von {@link #NORTHWEST}.
*
* <pre>
* NORTHWEST.contains(NORTH) // true
* SOUTHWEST.in(NORTH) // false
* NORTHWEST.in(UP) // true
* </pre>
*
* @param dir Eine andere Richtung.
* @return {@code true}, wenn diese Richtungen Teil der anderen ist,
* {@code false} sonst.
*/
public boolean contains( Direction dir ) {
return dir.in(this);
}
/**
* @return Diese Richtung als Vektor-Objekt.
*/
public Vector asVector() {
return new Vector(x, y);
}
/**
* Gibt die entgegengesetzte Richtung zu dieser zurück.
* Liefert die entgegengesetzte Richtung zu dieser.
* <p>
* Es wird die Art der Richtung berücksichtigt. Das bedeutet, das
* Inverse von {@link #UP} ist {@link #DOWN}, während das Inverse von
* {@link #NORTH} zu {@link #SOUTH} wird.
*
* @return
* @return Die entgegengesetzte Richtung zu dieser.
*/
public Direction inverse() {
for( Direction dir : Direction.values() ) {
if( dir.x == -this.x && dir.y == -this.y ) {
return dir;
}
}
switch( this ) {
case UP:
return DOWN;
case DOWN:
return UP;
case LEFT:
return RIGHT;
case RIGHT:
return LEFT;
case UPLEFT:
return DOWNRIGHT;
case UPRIGHT:
return DOWNLEFT;
case DOWNLEFT:
return UPRIGHT;
case DOWNRIGHT:
return UPLEFT;
case MIDDLE:
return MIDDLE;
case NORTH:
return SOUTH;
case SOUTH:
return NORTH;
case EAST:
return WEST;
case WEST:
return EAST;
case SOUTHWEST:
return NORTHEAST;
case SOUTHEAST:
return NORTHWEST;
case NORTHEAST:
return SOUTHWEST;
case NORTHWEST:
return SOUTHEAST;
default:
return CENTER;
}
}
}
}

View File

@@ -15,7 +15,7 @@ import java.awt.Stroke;
* {@link Strokeable#setStrokeColor(Color, int)} Methode hat, dann sollte auch
* eine {@link schule.ngb.zm.layers.TurtleLayer.Turtle} dieselbe Methode
* anbieten. Im Einzelfall kann es sinnvoll sein, weitere Methoden für
* Konturlinien zur erfügung zu stellen. Allerdings sollte davon nach
* Konturlinien zur verfügung zu stellen. Allerdings sollte davon nach
* Möglichkeit zugunsten einer einheitlichen API abgesehen werden.
* <p>
* Das Äquivalent für Füllungen stellt {@link Fillable} dar.

View File

@@ -28,7 +28,7 @@ public interface Updatable {
* @return {@code true}, wenn das Objekt aktiv ist, {@code false}
* andernfalls.
*/
public boolean isActive();
boolean isActive();
/**
* Änderung des Zustandes des Objekts abhängig vom Zeitintervall
@@ -39,6 +39,6 @@ public interface Updatable {
*
* @param delta Zeitintervall seit dem letzten Aufruf (in Sekunden).
*/
public void update( double delta );
void update( double delta );
}

View File

@@ -422,8 +422,8 @@ public class Vector extends Point2D.Double {
* dem quadrierten Abstand durchführen, wenn auch die gewünschte Entfernung
* quadriert wird.
*
* @param vector
* @return
* @param vector Ein anderer Vektor.
* @return Das Quadrat der Entfernung zum anderen Vektor.
*/
public double distanceSq( Vector vector ) {
return super.distanceSq(vector);

View File

@@ -9,9 +9,7 @@ import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
@@ -25,6 +23,12 @@ import java.util.ArrayList;
*/
public class Zeichenfenster extends JFrame {
/**
* Setzt das Look and Feel auf den Standard des Systems.
* <p>
* Sollte einmalig vor erstellen des erstyen Programmfensters aufgerufen
* werden.
*/
public static final void setLookAndFeel() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
@@ -33,6 +37,17 @@ public class Zeichenfenster extends JFrame {
}
}
/**
* Ermittelt ein {@link GraphicsDevice Anzeigegerät}, auf dem ein neues
* Zeichenfenster angezeigt werden soll. In der Regel ist dies der
* Bildschirm, auf dem sich derzeit der Mauszeiger befindet. Kann kein
* solcher Bildschirm ermittelt werden, wird das
* {@link GraphicsEnvironment#getDefaultScreenDevice() Standardgerät}
* zurückgegeben.
*
* @return Das Anzeigegerät, auf dem ein neues Fenster angezeigt werden
* sollte.
*/
public static final GraphicsDevice getGraphicsDevice() {
// Wir suchen den Bildschirm, der derzeit den Mauszeiger enthält, um
// das Zeichenfenster dort zu zentrieren.
@@ -55,10 +70,10 @@ public class Zeichenfenster extends JFrame {
}
/**
* Das Anzeigefenster, auf dem die ZM gestartet wurde (muss nicht gleich dem
* Aktuellen sein, wenn das Fenster verschoben wurde).
* Das Anzeigegerät, auf dem die Zeichenmaschine gestartet wurde (muss nicht
* gleich dem Aktuellen sein, wenn das Fenster verschoben wurde).
*/
private GraphicsDevice displayDevice;
private final GraphicsDevice displayDevice;
/**
* Bevorzugte Abmessungen der Zeichenleinwand. Für das Zeichenfenster hat es
@@ -90,20 +105,56 @@ public class Zeichenfenster extends JFrame {
}
};
private Zeichenleinwand canvas;
// Die Zeichenleinwand dieses Fensters.
private final Zeichenleinwand canvas;
/**
* Erstellt ein neues Zeichenfenster mit dem angegebenen Titel und einer
* {@link Zeichenleinwand} in der angegebenen Größe.
*
* @param width Die Breite der Zeichenleinwand.
* @param height Die Höhe der Zeichenleinwand.
* @param title Der Titel des Fensters.
*/
@SuppressWarnings( "unused" )
public Zeichenfenster( int width, int height, String title ) {
this(new Zeichenleinwand(width, height), title, getGraphicsDevice());
}
/**
* Erstellt ein neues Zeichenfenster mit dem angegebenen Titel und einer
* {@link Zeichenleinwand} in der angegebenen Größe auf dem angegebenen
* Anzeigegerät.
*
* @param width Die Breite der Zeichenleinwand.
* @param height Die Höhe der Zeichenleinwand.
* @param title Der Titel des Fensters.
* @param displayDevice Das Anzeigegerät für das Fenster.
*/
@SuppressWarnings( "unused" )
public Zeichenfenster( int width, int height, String title, GraphicsDevice displayDevice ) {
this(new Zeichenleinwand(width, height), title, displayDevice);
}
/**
* Erstellt ein neues Zeichenfenster mit dem angegebenen Titel und der
* angegebene {@link Zeichenleinwand}.
*
* @param canvas Die Zeichenleinwand.
* @param title Der Titel des Fensters.
*/
public Zeichenfenster( Zeichenleinwand canvas, String title ) {
this(canvas, title, getGraphicsDevice());
}
/**
* Erstellt ein neues Zeichenfenster mit dem angegebenen Titel und der
* angegebene {@link Zeichenleinwand} auf dem angegebenen Anzeigegerät.
*
* @param canvas Die Zeichenleinwand.
* @param title Der Titel des Fensters.
* @param displayDevice Das Anzeigegerät für das Fenster.
*/
public Zeichenfenster( Zeichenleinwand canvas, String title, GraphicsDevice displayDevice ) {
super(Validator.requireNotNull(displayDevice).getDefaultConfiguration());
this.displayDevice = displayDevice;
@@ -124,14 +175,19 @@ public class Zeichenfenster extends JFrame {
try {
if( Zeichenmaschine.MACOS ) {
URL iconUrl = Zeichenmaschine.class.getResource("icon_512.png");
if( iconUrl != null ) {
Image icon = ImageIO.read(iconUrl);
// Dock Icon in macOS setzen
Taskbar taskbar = Taskbar.getTaskbar();
taskbar.setIconImage(icon);
}
} else {
ArrayList<Image> icons = new ArrayList<>(4);
for( int size : new int[]{32, 64, 128, 512} ) {
icons.add(ImageIO.read(new File("icon_" + size + ".png")));
URL icnUrl = Zeichenmaschine.class.getResource("icon_" + size + ".png");
if( icnUrl != null ) {
icons.add(ImageIO.read(icnUrl));
}
}
this.setIconImages(icons);
@@ -150,19 +206,45 @@ public class Zeichenfenster extends JFrame {
// this.centerFrame();
}
/**
* Liefert das Anzeigegerät, auf dem dieses Fenster erstellt wurde.
* <p>
* Das Anzeigegerät muss nicht unbedingt gleich dem sein, auf dem sich das
* Fenster derzeit befindet, wenn das Fenster verschoben wurde.
*
* @return Das Anzeigegerät.
*/
@SuppressWarnings( "unused" )
public GraphicsDevice getDisplayDevice() {
return displayDevice;
}
/**
* Liefert die Abmessungen des Anzeigegeräts, auf dem das Fenster gestartet
* wurde.
*
* @return Die Abmessungen des Anzeigegeräts.
*/
public Rectangle getScreenBounds() {
// return GraphicsEnvironment.getLocalGraphicsEnvironment().getMaximumWindowBounds();
return displayDevice.getDefaultConfiguration().getBounds();
}
/**
* Liefert die Zeichenleinwand dieses Fensters.
*
* @return Die Zeichenleinwand.
*/
@SuppressWarnings( "unused" )
public Zeichenleinwand getCanvas() {
return canvas;
}
/**
* Liefert die Abmessungen der Zeichenleinwand zurück.
*
* @return Die Abmessungen der Zeichenleinwand.
*/
public Rectangle getCanvasBounds() {
return canvas.getBounds();
}
@@ -179,6 +261,12 @@ public class Zeichenfenster extends JFrame {
);
}
/**
* Setzt die Größe der Zeichenleinwand auf die angegebenen Werte.
*
* @param newWidth Neue Breite der Zeichenleinwand.
* @param newHeight Neue Höhe der Zeichenleinwand.
*/
public void setCanvasSize( int newWidth, int newHeight ) {
// TODO: (ngb) Put constrains on max/min frame/canvas size
if( fullscreen ) {
@@ -259,6 +347,12 @@ public class Zeichenfenster extends JFrame {
}
}
/**
* Prüft, ob sich dieses Zeichenfenster im Vollbild befindet.
*
* @return {@code true}, wenn das Fenster im Vollbild ist, {@code false}
* sonst.
*/
public boolean isFullscreen() {
Window win = displayDevice.getFullScreenWindow();
return fullscreen && win.equals(this);

View File

@@ -1,6 +1,5 @@
package schule.ngb.zm;
import schule.ngb.zm.layers.ColorLayer;
import schule.ngb.zm.util.Log;
import java.awt.Canvas;
@@ -8,7 +7,10 @@ import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Toolkit;
import java.awt.image.BufferStrategy;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
/**
* Eine Leinwand ist die Hauptkomponente einer Zeichenmaschine. Sie besteht aus
@@ -22,13 +24,13 @@ import java.util.*;
*/
public class Zeichenleinwand extends Canvas {
// Lokales Lock für Rendervorgänge.
private final Object[] renderLock = new Object[0];
/**
* Liste der hinzugefügten Ebenen.
*/
// Liste der hinzugefügten Ebenen.
private final List<Layer> layers;
// Status der Zeichenleinwand.
private boolean rendering = false, suspended = false;
/**
@@ -80,6 +82,10 @@ public class Zeichenleinwand extends Canvas {
}
}
/**
* Setzt das Zeichnen der Leinwand fort, falls es zuvor mit
* {@link #suspendRendering()} ausgesetzt wurde.
*/
public void resumeRendering() {
suspended = false;
}
@@ -201,6 +207,7 @@ public class Zeichenleinwand extends Canvas {
* @param <L> Typ der Ebenen, die abgefragt werden.
* @return Eine Liste mit den vorhandenen Ebenen des abgefragten Typs.
*/
@SuppressWarnings( "unused" )
public <L extends Layer> List<L> getLayers( Class<L> type ) {
ArrayList<L> result = new ArrayList<>(layers.size());
synchronized( layers ) {
@@ -213,10 +220,24 @@ public class Zeichenleinwand extends Canvas {
return result;
}
/**
* Entfernt die angegebene Ebene von dieser Zeichenleinwand.
*
* @param pLayer Die Ebene, die entfernt werden soll.
* @return {@code true}, wenn die Liste vorhanden war und entfernt wurde,
* {@code false} sonst.
*/
@SuppressWarnings( "unused" )
public boolean removeLayer( Layer pLayer ) {
return layers.remove(pLayer);
}
/**
* Entfernt alle angegebenen Ebenen von dieser Zeichenleinwand.
*
* @param removeLayers Die Ebenen, die entfernt werden sollen.
*/
@SuppressWarnings( "unused" )
public void removeLayers( Layer... removeLayers ) {
synchronized( layers ) {
for( Layer layer : removeLayers ) {
@@ -225,10 +246,21 @@ public class Zeichenleinwand extends Canvas {
}
}
/**
* Entfernt alle vorhandenen Ebenen von dieser Zeichenleinwand.
*/
@SuppressWarnings( "unused" )
public void clearLayers() {
layers.clear();
}
/**
* Aktualisiert alle {@link Layer Ebenen}, die dieser Zeichenleinwand
* hinzugefügt wurden.
*
* @param delta Die Zeit seit dem letzten Aufruf in Sekunden.
* @see Layer#update(double)
*/
public void updateLayers( double delta ) {
synchronized( layers ) {
for( Layer layer : List.copyOf(layers) ) {
@@ -261,9 +293,9 @@ public class Zeichenleinwand extends Canvas {
}
/**
* Zeichnet den Inhalt aller {@link Layer Ebenen} in den Grafik-Kontext.
* Zeichnet den Inhalt aller {@link Layer Ebenen} in den Grafikkontext.
*
* @param graphics
* @param graphics Der Grafikkontext.
*/
public void draw( Graphics graphics ) {
Graphics2D g2d = (Graphics2D) graphics.create();

View File

@@ -679,9 +679,9 @@ public class Zeichenmaschine extends Constants {
* Gibt die erste (unterste) {@link Layer Ebene} der angegebenen Klasse
* zurück.
*
* <pre>
* <pre><code>
* DrawingLayer draw = getLayer(DrawingLayer.class);
* </pre>
* </code></pre>
*
* @param layerClass
* @param <LT>
@@ -947,9 +947,9 @@ public class Zeichenmaschine extends Constants {
* <p>
* Die Konstanten der Klasse {@link Cursor} definieren 13 Standardzeiger,
* die durch angabe der Nummer geladen werden können.
* <pre>
* <pre><code>
* setCursor(Cursor.HAND_CURSOR);
* </pre>
* </code></pre>
*
* @param pPredefinedCursor Eine der Cursor-Konstanten.
* @see Cursor
@@ -1022,9 +1022,9 @@ public class Zeichenmaschine extends Constants {
* {@code delta} wird in Sekunden angegeben. Um eine Form zum Beispiel um
* {@code 50} Pixel pro Sekunde in {@code x}-Richtung zu bewegen, kann so
* vorgegangen werden:
* <pre>
* <pre><code>
* shape.move(50*delta, 0.0);
* </pre>
* </code></pre>
*
* @param delta
*/

View File

@@ -30,7 +30,7 @@ public final class FileLoader {
}
/**
* Lädt die angegebene Datei Zeilenweise in ein Array.
* Lädt die angegebene Datei Zeilenweise in eine Liste.
*
* @param source
* @param charset
@@ -161,7 +161,7 @@ public final class FileLoader {
).toArray(double[][]::new);
}
public FileLoader() {
private FileLoader() {
}
private static final Log LOG = Log.getLogger(FileLoader.class);