mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-10-12 09:56:33 +02:00
Compare commits
11 Commits
d500c130ed
...
788ed888e9
| Author | SHA1 | Date | |
|---|---|---|---|
| 788ed888e9 | |||
| ce3ffee4da | |||
| 74c85e0f61 | |||
| c7b2a520c4 | |||
| c5c046521b | |||
| 9834b9c389 | |||
| eaaca6b90f | |||
| 1275af55f3 | |||
| 632038030e | |||
| cec17f0d7c | |||
| b29532bf6e |
13
build.gradle
13
build.gradle
@@ -33,6 +33,19 @@ dependencies {
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
|
||||
}
|
||||
|
||||
javadoc {
|
||||
options {
|
||||
encoding = "UTF-8"
|
||||
overview = "src/main/java/overview.html"
|
||||
// title = "Die Zeichenmaschine"
|
||||
|
||||
// options.links 'https://docs.oracle.com/javase/8/docs/api/'
|
||||
// options.links 'https://docs.oracle.com/javaee/7/api'
|
||||
options.links 'https://docs.oracle.com/en/java/javase/11/docs/api'
|
||||
}
|
||||
options.addStringOption("charset", "UTF-8")
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
9
src/main/java/overview.html
Normal file
9
src/main/java/overview.html
Normal file
@@ -0,0 +1,9 @@
|
||||
<HTML>
|
||||
<BODY>
|
||||
Die Zeichenmaschine
|
||||
<p>
|
||||
<h2>Die Zeichenmaschine</h2>
|
||||
|
||||
@author J. Neugebauer
|
||||
</BODY>
|
||||
</HTML>
|
||||
@@ -1,9 +1,8 @@
|
||||
package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.anim.Easing;
|
||||
import schule.ngb.zm.util.Validator;
|
||||
import schule.ngb.zm.util.io.ImageLoader;
|
||||
import schule.ngb.zm.util.Noise;
|
||||
import schule.ngb.zm.util.io.ImageLoader;
|
||||
|
||||
import java.awt.Cursor;
|
||||
import java.awt.Font;
|
||||
@@ -24,7 +23,7 @@ import java.util.function.DoubleUnaryOperator;
|
||||
* aktuell gehalten werden (beispielsweise {@link #runtime}).
|
||||
* <p>
|
||||
* Für die Implementierung eigener Klassen ist es oft hilfreich von
|
||||
* {@code Constants} zu erben, um die Methoden und Konstanten einfach im
|
||||
* {@code Constants} zu erben, um die Methoden und Konstanten einfacher im
|
||||
* Programm nutzen zu können.
|
||||
* <pre><code>
|
||||
* class MyClass extends Constants {
|
||||
@@ -1256,7 +1255,7 @@ public class Constants {
|
||||
public static final double distance( double fromX, double fromY, double toX, double toY ) {
|
||||
double diffX = toX - fromX;
|
||||
double diffY = toY - fromY;
|
||||
return sqrt(diffX*diffX + diffY*diffY);
|
||||
return sqrt(diffX * diffX + diffY * diffY);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1321,7 +1320,8 @@ public class Constants {
|
||||
}
|
||||
|
||||
/**
|
||||
* Erzeugt eine ganze Pseudozufallszahl zwischen {@code 0} und {@code max}.
|
||||
* Erzeugt eine ganze Pseudozufallszahl zwischen {@code 0} und {@code max}
|
||||
* (einschließlich der Grenzen).
|
||||
*
|
||||
* @param max Obere Grenze.
|
||||
* @return Eine Zufallszahl.
|
||||
@@ -1332,7 +1332,7 @@ public class Constants {
|
||||
|
||||
/**
|
||||
* Erzeugt eine ganze Pseudozufallsganzzahl zwischen {@code min} und
|
||||
* {@code max}.
|
||||
* {@code max} (einschließlich der Grenzen).
|
||||
*
|
||||
* @param min Untere Grenze.
|
||||
* @param max Obere Grenze.
|
||||
@@ -1395,9 +1395,9 @@ public class Constants {
|
||||
* @param values Ein Array mit Werten, die zur Auswahl stehen.
|
||||
* @return Ein zufälliges Element aus dem Array.
|
||||
*/
|
||||
/*public static final int choice( int... values ) {
|
||||
public static final int choice( int... values ) {
|
||||
return values[random(0, values.length - 1)];
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Wählt ein zufälliges Element aus dem Array aus.
|
||||
@@ -1405,9 +1405,9 @@ public class Constants {
|
||||
* @param values Ein Array mit Werten, die zur Auswahl stehen.
|
||||
* @return Ein zufälliges Element aus dem Array.
|
||||
*/
|
||||
/*public static final double choice( double... values ) {
|
||||
public static final double choice( double... values ) {
|
||||
return values[random(0, values.length - 1)];
|
||||
}*/
|
||||
}
|
||||
|
||||
/**
|
||||
* Wählt ein zufälliges Element aus dem Array aus.
|
||||
@@ -1416,6 +1416,7 @@ public class Constants {
|
||||
* @param <T> Datentyp des Elements.
|
||||
* @return Ein zufälliges Element aus dem Array.
|
||||
*/
|
||||
@SafeVarargs
|
||||
public static final <T> T choice( T... values ) {
|
||||
return values[random(0, values.length - 1)];
|
||||
}
|
||||
|
||||
@@ -201,6 +201,8 @@ public interface Strokeable extends Drawable {
|
||||
* Kontureigenschaften zu erstellen. Der aktuelle {@code Stroke} wird
|
||||
* zwischengespeichert.
|
||||
*
|
||||
* @param strokeType
|
||||
* @param strokeWeight
|
||||
* @return Ein {@code Stroke} mit den passenden Kontureigenschaften.
|
||||
*/
|
||||
static Stroke createStroke( Options.StrokeType strokeType, double strokeWeight ) {
|
||||
|
||||
@@ -156,7 +156,7 @@ public class Zeichenfenster extends JFrame {
|
||||
* @param displayDevice Das Anzeigegerät für das Fenster.
|
||||
*/
|
||||
public Zeichenfenster( Zeichenleinwand canvas, String title, GraphicsDevice displayDevice ) {
|
||||
super(Validator.requireNotNull(displayDevice).getDefaultConfiguration());
|
||||
super(Validator.requireNotNull(displayDevice, "displayDevice").getDefaultConfiguration());
|
||||
this.displayDevice = displayDevice;
|
||||
|
||||
Validator.requireNotNull(canvas, "Every Zeichenfenster needs a Zeichenleinwand, but got <null>.");
|
||||
|
||||
@@ -24,7 +24,7 @@ public abstract class Animation<T> extends Constants implements Updatable {
|
||||
|
||||
public Animation( DoubleUnaryOperator easing ) {
|
||||
this.runtime = Constants.DEFAULT_ANIM_RUNTIME;
|
||||
this.easing = Validator.requireNotNull(easing);
|
||||
this.easing = Validator.requireNotNull(easing, "easing");
|
||||
}
|
||||
|
||||
public Animation( int runtime ) {
|
||||
@@ -34,7 +34,7 @@ public abstract class Animation<T> extends Constants implements Updatable {
|
||||
|
||||
public Animation( int runtime, DoubleUnaryOperator easing ) {
|
||||
this.runtime = runtime;
|
||||
this.easing = Validator.requireNotNull(easing);
|
||||
this.easing = Validator.requireNotNull(easing, "easing");
|
||||
}
|
||||
|
||||
public int getRuntime() {
|
||||
|
||||
@@ -10,7 +10,7 @@ public class AnimationFacade<S> extends Animation<S> {
|
||||
|
||||
public AnimationFacade( Animation<S> anim, int runtime, DoubleUnaryOperator easing ) {
|
||||
super(runtime, easing);
|
||||
this.anim = Validator.requireNotNull(anim);
|
||||
this.anim = Validator.requireNotNull(anim, "anim");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -9,7 +9,6 @@ public class AnimationGroup<T> extends Animation<T> {
|
||||
|
||||
List<Animation<T>> anims;
|
||||
|
||||
|
||||
private boolean overrideEasing = false;
|
||||
|
||||
private int overrideRuntime = -1;
|
||||
|
||||
@@ -123,8 +123,8 @@ public class Animations {
|
||||
}
|
||||
|
||||
public static final <T> Future<T> animateProperty( T target, final double from, final double to, int runtime, DoubleUnaryOperator easing, DoubleConsumer propSetter ) {
|
||||
Validator.requireNotNull(target);
|
||||
Validator.requireNotNull(propSetter);
|
||||
Validator.requireNotNull(target, "target");
|
||||
Validator.requireNotNull(propSetter, "propSetter");
|
||||
return play(target, runtime, easing, ( e ) -> propSetter.accept(Constants.interpolate(from, to, e)));
|
||||
}
|
||||
|
||||
|
||||
12
src/main/java/schule/ngb/zm/anim/package-info.java
Normal file
12
src/main/java/schule/ngb/zm/anim/package-info.java
Normal file
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Dieses Paket enthält Klassen zur Animation von
|
||||
* {@link schule.ngb.zm.shapes.Shape} Objekten auf einem
|
||||
* {@link schule.ngb.zm.layers.ShapesLayer}.
|
||||
* <p>
|
||||
* Mit den Animationsklassen lassen sich neben {@code Shape} Objekten aber auch
|
||||
* andere Objekte animieren.
|
||||
* <p>
|
||||
* Das Paket setzt auf den funktionalen Programmierschnittstellen von Java auf
|
||||
* und kann als Einführung in das Paradigma dienen.
|
||||
*/
|
||||
package schule.ngb.zm.anim;
|
||||
8
src/main/java/schule/ngb/zm/layers/package-info.java
Normal file
8
src/main/java/schule/ngb/zm/layers/package-info.java
Normal file
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Dieses Paket enthält implementationen der abstrakten
|
||||
* {@link schule.ngb.zm.Layer} Klasse.
|
||||
* <p>
|
||||
* {@code Layer} sind Ebenen, die der {@link schule.ngb.zm.Zeichenleinwand}
|
||||
* hinzugefügt und pro Frame gerendert werden.
|
||||
*/
|
||||
package schule.ngb.zm.layers;
|
||||
@@ -84,7 +84,7 @@ public class Music implements Audio {
|
||||
* @see ResourceStreamProvider#getResourceURL(String)
|
||||
*/
|
||||
public Music( String audioSource ) {
|
||||
Validator.requireNotNull(audioSource);
|
||||
Validator.requireNotNull(audioSource, "audioSource");
|
||||
this.audioSource = audioSource;
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,7 @@ public class Sound implements Audio {
|
||||
* @see ResourceStreamProvider#getResourceURL(String)
|
||||
*/
|
||||
public Sound( String source ) {
|
||||
Validator.requireNotNull(source);
|
||||
Validator.requireNotNull(source, "source");
|
||||
this.audioSource = source;
|
||||
}
|
||||
|
||||
|
||||
7
src/main/java/schule/ngb/zm/media/package-info.java
Normal file
7
src/main/java/schule/ngb/zm/media/package-info.java
Normal file
@@ -0,0 +1,7 @@
|
||||
/**
|
||||
* Dieses Paket enthält Klassen zur Einbettung von Mediendateien.
|
||||
* <p>
|
||||
* Mit Medien sind vor allem Audio und Videodateien gemeint. Aktuell kann die
|
||||
* Zeichenmaschine Audiodateien verwenden.
|
||||
*/
|
||||
package schule.ngb.zm.media;
|
||||
16
src/main/java/schule/ngb/zm/ml/package-info.java
Normal file
16
src/main/java/schule/ngb/zm/ml/package-info.java
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Dieses Paekt enthält Klassen für Experimente mit Verfahren des maschinellen
|
||||
* Lernens (ML).
|
||||
* <p>
|
||||
* Die hier implementierten Klassen sind eine prototypische Umsetzung von
|
||||
* einfachen neuronalen Netzwerken, mit denen an kleinen Problemstellungen
|
||||
* experimentell Modelle trainiert und angewandt werden können.
|
||||
* <p>
|
||||
* Die Implementierungen sind nicht optimiert und setzen auf native
|
||||
* Java-Methoden. Daher sind sie nur für die Anwendung auf extrem kleine Modelle
|
||||
* in Bildungskontexten gedacht.
|
||||
* <p>
|
||||
* Durch Einbettung wissenschaftlicher Bibliotheken mit optimierten Operationen
|
||||
* lassen sich bessere Ergebnisse erreichen.
|
||||
*/
|
||||
package schule.ngb.zm.ml;
|
||||
13
src/main/java/schule/ngb/zm/package-info.java
Normal file
13
src/main/java/schule/ngb/zm/package-info.java
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* <h2>Die Zeichenmaschine</h2>
|
||||
* <p>
|
||||
* Die <b>Zeichenmaschine</b> ist eine für den Informatikunterricht entwickelte
|
||||
* Bibliothek, die unter anderem an <a
|
||||
* href="https://processing.org/">Processing</a> angelehnt ist. Die Bibliothek
|
||||
* soll einige der üblichen Anfängerschwierigkeiten mit Java vereinfachen und
|
||||
* für Schülerinnen und Schüler im Unterricht nutzbar machen.
|
||||
* <p>
|
||||
* Eine umfassende Dokumentation ist unter <a
|
||||
* href="https://zeichenmaschine.xyz">zeichenmaschine.xyz</a> verfügbar.
|
||||
*/
|
||||
package schule.ngb.zm;
|
||||
@@ -4,13 +4,14 @@ import schule.ngb.zm.BasicDrawable;
|
||||
import schule.ngb.zm.Fillable;
|
||||
import schule.ngb.zm.Options;
|
||||
import schule.ngb.zm.Strokeable;
|
||||
import schule.ngb.zm.util.Validator;
|
||||
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.awt.geom.Point2D;
|
||||
|
||||
/**
|
||||
* Basisklasse für alle Formen in der Zeichenmaschine.
|
||||
* Dies ist die Basisklasse für alle Formen in der Zeichenmaschine.
|
||||
* <p>
|
||||
* Alle Formen sind als Unterklassen von {@code Shape} implementiert.
|
||||
* <p>
|
||||
@@ -19,7 +20,6 @@ import java.awt.geom.Point2D;
|
||||
* Parametern initialisiert und einen, der die Werte einer anderen Form
|
||||
* desselben Typs übernimmt. In der Klasse {@link Circle} sind die Konstruktoren
|
||||
* beispielsweise so implementiert:
|
||||
*
|
||||
* <pre><code>
|
||||
* public Circle( double x, double y, double radius ) {
|
||||
* super(x, y);
|
||||
@@ -39,42 +39,42 @@ import java.awt.geom.Point2D;
|
||||
public abstract class Shape extends BasicDrawable {
|
||||
|
||||
/**
|
||||
* x-Koordinate der Form.
|
||||
* Speichert die x-Koordinate der Form.
|
||||
*/
|
||||
protected double x;
|
||||
|
||||
/**
|
||||
* y-Koordinate der Form.
|
||||
* Speichert die y-Koordinate der Form.
|
||||
*/
|
||||
protected double y;
|
||||
|
||||
/**
|
||||
* Rotation in Grad um den Punkt (x, y).
|
||||
* Speichert die Rotation in Grad um den Punkt (x, y).
|
||||
*/
|
||||
protected double rotation = 0.0;
|
||||
|
||||
/**
|
||||
* Skalierungsfaktor.
|
||||
* Speichert den Skalierungsfaktor.
|
||||
*/
|
||||
protected double scale = 1.0;
|
||||
|
||||
/**
|
||||
* Ankerpunkt der Form.
|
||||
* Speichert den Ankerpunkt.
|
||||
*/
|
||||
protected Options.Direction anchor = Options.Direction.CENTER;
|
||||
|
||||
/**
|
||||
* Setzt die x- und y-Koordinate der Form auf 0.
|
||||
* Erstellt eine neue Form mit den Koordinaten {@code (0,0)}.
|
||||
*/
|
||||
public Shape() {
|
||||
this(0.0, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die x- und y-Koordinate der Form.
|
||||
* Erstellt eine Form mit den angegebenen Koordinaten.
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param x Die x-Koordinate.
|
||||
* @param y Die y-Koordinate.
|
||||
*/
|
||||
public Shape( double x, double y ) {
|
||||
this.x = x;
|
||||
@@ -82,7 +82,7 @@ public abstract class Shape extends BasicDrawable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die x-Koordinate der Form zurück.
|
||||
* Liefert die aktuelle x-Koordinate der Form.
|
||||
*
|
||||
* @return Die x-Koordinate.
|
||||
*/
|
||||
@@ -100,7 +100,7 @@ public abstract class Shape extends BasicDrawable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die y-Koordinate der Form zurück.
|
||||
* Liefert die aktuelle y-Koordinate der Form.
|
||||
*
|
||||
* @return Die y-Koordinate.
|
||||
*/
|
||||
@@ -109,57 +109,44 @@ public abstract class Shape extends BasicDrawable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die y-Koordinate der Form.
|
||||
* Setzt die x-Koordinate der Form.
|
||||
*
|
||||
* @param y Die neue y-Koordinate.
|
||||
* @param y Die neue y-Koordinate der Form.
|
||||
*/
|
||||
public void setY( double y ) {
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Breite dieser Form zurück.
|
||||
* Liefert die aktuelle Breite dieser Form.
|
||||
* <p>
|
||||
* Die Breite einer Form ist immer die Breite ihrer Begrenzung,
|
||||
* <strong>bevor</strong> Drehungen und andere Transformationen auf sie
|
||||
* angewandt wurden.
|
||||
* <p>
|
||||
* Die Begrenzungen der tatsächlich gezeichneten Form kann mit
|
||||
* {@link #getBounds()} abgerufen werden.
|
||||
* Die Begrenzungen der tatsächlich gezeichneten Form wird mit
|
||||
* {@link #getBounds()} abgerufen.
|
||||
*
|
||||
* @return
|
||||
* @return Die Breite der Form.
|
||||
*/
|
||||
public abstract double getWidth();
|
||||
|
||||
/**
|
||||
* Gibt die Höhe dieser Form zurück.
|
||||
* Liefert die aktuelle Höhe dieser Form.
|
||||
* <p>
|
||||
* Die Höhe einer Form ist immer die Höhe ihrer Begrenzung,
|
||||
* <strong>bevor</strong> Drehungen und andere Transformationen auf sie
|
||||
* angewandt wurden.
|
||||
* <p>
|
||||
* Die Begrenzungen der tatsächlich gezeichneten Form kann mit
|
||||
* {@link #getBounds()} abgerufen werden.
|
||||
* Die Begrenzungen der tatsächlich gezeichneten Form wird mit
|
||||
* {@link #getBounds()} abgerufen.
|
||||
*
|
||||
* @return
|
||||
* @return Die Höhe der Form.
|
||||
*/
|
||||
public abstract double getHeight();
|
||||
|
||||
@Override
|
||||
public void setGradient( schule.ngb.zm.Color from, schule.ngb.zm.Color to, Options.Direction dir ) {
|
||||
Point2D apDir = getAbsAnchorPoint(dir);
|
||||
Point2D apInv = getAbsAnchorPoint(dir.inverse());
|
||||
setGradient(apInv.getX(), apInv.getY(), from, apDir.getX(), apDir.getY(), to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGradient( schule.ngb.zm.Color from, schule.ngb.zm.Color to ) {
|
||||
Point2D ap = getAbsAnchorPoint(CENTER);
|
||||
setGradient(ap.getX(), ap.getY(), Math.min(ap.getX(), ap.getY()), from, to);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt die Rotation in Grad zurück.
|
||||
* Liefert die Rotation in Grad.
|
||||
*
|
||||
* @return Rotation in Grad.
|
||||
*/
|
||||
@@ -176,14 +163,25 @@ public abstract class Shape extends BasicDrawable {
|
||||
this.rotation += angle % 360;
|
||||
}
|
||||
|
||||
public void rotateTo( double angle ) {
|
||||
this.rotation = angle % 360;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dreht die Form um den angegebenen Winkel um das angegebene Drehzentrum.
|
||||
*
|
||||
* @param center Das Drehzentrum der Drehung.
|
||||
* @param angle Der Drehwinkel.
|
||||
*/
|
||||
public void rotate( Point2D center, double angle ) {
|
||||
Validator.requireNotNull(center, "center");
|
||||
rotate(center.getX(), center.getY(), angle);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dreht die Form um den angegebenen Drehwinkel um die angegbenen
|
||||
* Koordinaten als Drehzentrum.
|
||||
*
|
||||
* @param x x-Koordiante des Drehzentrums.
|
||||
* @param y y-Koordiante des Drehzentrums.
|
||||
* @param angle Drehwinkel in Grad.
|
||||
*/
|
||||
public void rotate( double x, double y, double angle ) {
|
||||
this.rotation += angle % 360;
|
||||
|
||||
@@ -198,6 +196,15 @@ public abstract class Shape extends BasicDrawable {
|
||||
this.y = y2 + y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt die Drehung der Form auf den angegebenen Winkel.
|
||||
*
|
||||
* @param angle Drehwinkel in Grad.
|
||||
*/
|
||||
public void rotateTo( double angle ) {
|
||||
this.rotation = angle % 360;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gibt den aktuellen Skalierungsfaktor zurück.
|
||||
*
|
||||
@@ -207,34 +214,92 @@ public abstract class Shape extends BasicDrawable {
|
||||
return scale;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Skalierungsfaktor auf den angegebenen Faktor.
|
||||
* <p>
|
||||
* Bei einem Faktor größer 0 wird die Form vergrößert, bei einem Faktor
|
||||
* kleiner 0 verkleinert. Bei negativen Werten wird die Form entlang der x-
|
||||
* bzw. y-Achse gespiegelt.
|
||||
* <p>
|
||||
* Das Seitenverhältnis wird immer beibehalten.
|
||||
*
|
||||
* @param factor Der Skalierungsfaktor.
|
||||
*/
|
||||
public void scale( double factor ) {
|
||||
scale = factor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Skaliert die Form um den angegebenen Faktor.
|
||||
* <p>
|
||||
* Bei einem Faktor größer 0 wird die Form vergrößert, bei einem Faktor
|
||||
* kleiner 0 verkleinert. Bei negativen Werten wird die Form entlang der x-
|
||||
* bzw. y-Achse gespiegelt.
|
||||
* <p>
|
||||
* Die Skalierung wird zusätzlich zur aktuellen Skalierung angewandt. Wurde
|
||||
* die Form zuvor um den Faktor 0.5 verkleinert und wird dann um 1.5
|
||||
* vergrößert, dann ist die Form im Anschluss ein Drittel kleiner als zu
|
||||
* Beginn ({@code 0.5 * 1.5 = 0.75}).
|
||||
*
|
||||
* @param factor Der Skalierungsfaktor.
|
||||
*/
|
||||
public void scaleBy( double factor ) {
|
||||
scale(scale * factor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Liefert den aktuellen Ankerpunkt der Form.
|
||||
*
|
||||
* @return Der Ankerpunkt.
|
||||
*/
|
||||
public Options.Direction getAnchor() {
|
||||
return anchor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setzt den Ankerpunkt der Form basierend auf der angegebenen
|
||||
* {@link Options.Direction Richtung}.
|
||||
* Setzt den Ankerpunkt der Form auf die angegebene Richtung.
|
||||
* <p>
|
||||
* Für das Setzen des Ankers muss das
|
||||
* {@link #getBounds() begrenzende Rechteck} berechnet werden. Unterklassen
|
||||
* sollten die Methode überschreiben, wenn der Anker auch direkt gesetzt
|
||||
* werden kann.
|
||||
* Jede Form hat einen Ankerpunkt, von dem aus sie gezeichnet wird. Jede
|
||||
* {@link schule.ngb.zm.Options.Direction Richtung} beschreibt einen der
|
||||
* Neun Ankerpunkte:
|
||||
* <pre>
|
||||
* NW────N────NE
|
||||
* │ │
|
||||
* │ │
|
||||
* W C E
|
||||
* │ │
|
||||
* │ │
|
||||
* SW────S────SE
|
||||
* </pre>
|
||||
* <p>
|
||||
* Für den Ankerpunkt {@link #CENTER} wird die Form also ausgehend von den
|
||||
* Koordinaten {@link #x} und {@link #y} um die Hälfte der Breite nach links
|
||||
* und rechts, sowie um die Hälfte der Höhe nach oben und unten gezeichnet.
|
||||
* Fpr den Ankerpunkt {@link #NORTHWEST} dagegen um die gesamte Breite nach
|
||||
* rechts und die Höhe nach unten.
|
||||
* <pre>
|
||||
* setAnchor(CENTER) │ setAnchor(NORTHWEST)
|
||||
* ┌───────────┐ │
|
||||
* │ │ │
|
||||
* │ │ │
|
||||
* │ (x,y) │ │ (x,y)─────────┐
|
||||
* │ │ │ │ │
|
||||
* │ │ │ │ │
|
||||
* └───────────┘ │ │ │
|
||||
* │ │ │
|
||||
* │ │ │
|
||||
* │ └───────────┘
|
||||
* </pre>
|
||||
* <p>
|
||||
* Der Ankerpunkt der Form bestimmt bei Transformationen auch die Position
|
||||
* des Drehzentrums und anderer relativer Koordinaten bezüglich der Form.
|
||||
*
|
||||
* @param anchor
|
||||
* @param anchor Der Ankerpunkt.
|
||||
*/
|
||||
public void setAnchor( Options.Direction anchor ) {
|
||||
if( anchor != null ) {
|
||||
Validator.requireNotNull(anchor, "anchor");
|
||||
this.anchor = anchor;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bestimmt die relativen Koordinaten des angegebenen Ankerpunkts basierend
|
||||
@@ -242,7 +307,19 @@ public abstract class Shape extends BasicDrawable {
|
||||
* <p>
|
||||
* Die Koordinaten des Ankerpunktes werden relativ zur oberen linken Ecke
|
||||
* des Rechtecks mit der Breite {@code width} und der Höhe {@code height}
|
||||
* bestimmt.
|
||||
* bestimmt. Der Ankerpunkt {@link #NORTHWEST} hat daher immer das Ergebnis
|
||||
* {@code (0,0)} und {@link #SOUTHEAST} {@code (width, height)}.
|
||||
* <pre>
|
||||
* (0,0)───(w/2,0)───(w,0)
|
||||
* │ │
|
||||
* │ │
|
||||
* │ │
|
||||
* (0,h/2) (w/2,h/2) (w,h/2)
|
||||
* │ │
|
||||
* │ │
|
||||
* │ │
|
||||
* (0,h)───(w/2,h)───(w,h)
|
||||
* </pre>
|
||||
*
|
||||
* @param width Breite des umschließenden Rechtecks.
|
||||
* @param height Höhe des umschließenden Rechtecks.
|
||||
@@ -259,11 +336,12 @@ public abstract class Shape extends BasicDrawable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Bestimmt den Ankerpunkt der Form relativ zum gesetzten
|
||||
* {@link #setAnchor(Options.Direction) Ankerpunkt}.
|
||||
* Bestimmt die Koordinaten des angegebenen Ankers der Form relativ zum
|
||||
* aktuellen {@link #setAnchor(Options.Direction) Ankerpunkt}.
|
||||
*
|
||||
* @param anchor Die Richtung des Ankerpunktes.
|
||||
* @param anchor Die Richtung des Ankers.
|
||||
* @return Der relative Ankerpunkt.
|
||||
* @see #getAnchorPoint(double, double, Options.Direction)
|
||||
*/
|
||||
public Point2D.Double getAnchorPoint( Options.Direction anchor ) {
|
||||
double wHalf = getWidth() * .5, hHalf = getHeight() * .5;
|
||||
@@ -276,11 +354,20 @@ public abstract class Shape extends BasicDrawable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Ermittelt die absoluten Koordinaten eines angegebenen
|
||||
* Ermittelt die absoluten Koordinaten des angegebenen
|
||||
* {@link #setAnchor(Options.Direction) Ankers}.
|
||||
* <p>
|
||||
* Die absoluten Koordinaten werden bestimmt durch die Position der Form
|
||||
* {@code (x,y)} plus die
|
||||
* {@link #getAnchorPoint(Options.Direction) relativen Koordinaten} des
|
||||
* Ankers.
|
||||
*
|
||||
* @param anchor Die Richtung des Ankerpunktes.
|
||||
* <b>Wichtig:</b> Die Berechnung berücksichtigt derzeit keine Rotationen
|
||||
* und Transformationen der Form.
|
||||
*
|
||||
* @param anchor Die Richtung des Ankers.
|
||||
* @return Der absolute Ankerpunkt.
|
||||
* @see #getAnchorPoint(double, double, Options.Direction)
|
||||
*/
|
||||
public Point2D.Double getAbsAnchorPoint( Options.Direction anchor ) {
|
||||
// TODO: Die absoluten Anker müssten eigentlich die Rotation berücksichtigen.
|
||||
@@ -293,20 +380,22 @@ public abstract class Shape extends BasicDrawable {
|
||||
/**
|
||||
* Kopiert die Eigenschaften der angegebenen Form in diese.
|
||||
* <p>
|
||||
* Unterklassen sollten diese Methode überschreiben, um weitere
|
||||
* Eigenschaften zu kopieren (zum Beispiel den Radius eines Kreises).
|
||||
* Unterklassen sollten immer mit dem Aufruf {@code super.copyFrom(shape)}
|
||||
* die Basiseigenschaften kopieren.
|
||||
* Unterklassen überschreiben diese Methode, um weitere Eigenschaften zu
|
||||
* kopieren (zum Beispiel den Radius eines Kreises). Überschreibende
|
||||
* Methoden sollten immer mit dem Aufruf {@code super.copyFrom(shape)} die
|
||||
* Basiseigenschaften kopieren.
|
||||
* <p>
|
||||
* Die Methode sollte so viele Eigenschaften wie möglich von der anderen
|
||||
* Form in diese kopieren. Wenn die andere Form einen anderen Typ hat, dann
|
||||
* werden trotzdem die Basiseigenschaften (Konturlinie, Füllung, Position,
|
||||
* Rotation, Skalierung, Sichtbarkeit und Ankerpunkt) in diese Form kopiert.
|
||||
* Implementierende Unterklassen können soweit sinnvoll auch andere Werte
|
||||
* übernehmen. Eine {@link Ellipse} kann beispielsweise auch die Breite und
|
||||
* Höhe eines {@link Rectangle} übernehmen.
|
||||
* Die Methode kopiert so viele Eigenschaften wie möglich von der
|
||||
* angegebenen Form in diese. Wenn die andere Form einen anderen Typ hat,
|
||||
* dann werden trotzdem die Basiseigenschaften (Konturlinie, Füllung,
|
||||
* Position, Rotation, Skalierung, Sichtbarkeit und Ankerpunkt) in diese
|
||||
* Form kopiert. Soweit sinnvoll übernehmen implementierende Unterklassen
|
||||
* auch andere Werte. Eine {@link Ellipse} kopiert beispielsweise auch die
|
||||
* Breite und Höhe eines {@link Rectangle}.
|
||||
* <p>
|
||||
* Wird {@code null} übergeben, dann passiert nichts.
|
||||
*
|
||||
* @param shape Die Originalform, von der kopiert werden soll.
|
||||
* @param shape Die Originalform, von der kopiert wird.
|
||||
*/
|
||||
public void copyFrom( Shape shape ) {
|
||||
if( shape != null ) {
|
||||
@@ -335,9 +424,9 @@ public abstract class Shape extends BasicDrawable {
|
||||
* </code></pre>
|
||||
* <p>
|
||||
* Die Methode kann beliebig umgesetzt werden, um eine 1-zu-1-Kopie dieser
|
||||
* Form zu erhalten. In der Regel sollte aber jede Form einen Konstruktor
|
||||
* besitzen, die alle Werte einer andern Form übernimmt. Die gezeigte
|
||||
* Implementierung dürfte daher im Regelfall ausreichend sein.
|
||||
* Form zu erhalten. In der Regel besitzt aber jede Form einen Konstruktor,
|
||||
* der alle Werte einer andern Form übernimmt. Die gezeigte Implementierung
|
||||
* ist daher im Regelfall ausreichend.
|
||||
*
|
||||
* @return Eine genaue Kopie dieser Form.
|
||||
*/
|
||||
@@ -348,8 +437,8 @@ public abstract class Shape extends BasicDrawable {
|
||||
* zurück. Intern werden die AWT Shapes benutzt, um sie auf den
|
||||
* {@link Graphics2D Grafikkontext} zu zeichnen.
|
||||
* <p>
|
||||
* Wenn diese Form nicht durch eine AWT-Shape dargestellt wird, kann die
|
||||
* Methode {@code null} zurückgeben.
|
||||
* Wenn diese Form nicht durch eine AWT-Shape dargestellt wird, liefert die
|
||||
* Methode {@code null}.
|
||||
*
|
||||
* @return Eine Java-AWT {@code Shape} die diese Form repräsentiert oder
|
||||
* {@code null}.
|
||||
@@ -369,34 +458,85 @@ public abstract class Shape extends BasicDrawable {
|
||||
return new Bounds(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verschiebt die Form um die angegebenen Werte entlang der
|
||||
* Koordinatenachsen.
|
||||
*
|
||||
* @param dx Verschiebung entlang der x-Achse.
|
||||
* @param dy Verschiebung entlang der y-Achse.
|
||||
*/
|
||||
public void move( double dx, double dy ) {
|
||||
x += dx;
|
||||
y += dy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bewegt die Form an die angegebenen Koordinaten.
|
||||
*
|
||||
* @param x Die neue x-Koordinate.
|
||||
* @param y Die neue y-Koordinate.
|
||||
*/
|
||||
public void moveTo( double x, double y ) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bewegt die Form an dieselben Koordinaten wie die angegebene Form.
|
||||
*
|
||||
* @param shape Eine andere Form.
|
||||
*/
|
||||
public void moveTo( Shape shape ) {
|
||||
moveTo(shape.getX(), shape.getY());
|
||||
}
|
||||
|
||||
/**
|
||||
* Bewegt die Form zum angegebenen Ankerpunkt der angegebenen Form.
|
||||
*
|
||||
* @param shape Die andere Form.
|
||||
* @param dir Die Richtung des Ankerpunktes.
|
||||
* @see #moveTo(Shape, Options.Direction, double)
|
||||
*/
|
||||
public void moveTo( Shape shape, Options.Direction dir ) {
|
||||
moveTo(shape, dir, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bewegt den Ankerpunkt dieser Form zu einem Ankerpunkt einer anderen Form.
|
||||
* Mit {@code buff} kann ein zusätzlicher Abstand angegeben werden, um den
|
||||
* die Form entlang des Ankerpunktes {@code anchor} verschoben werden soll.
|
||||
* Bewegt den Ankerpunkt dieser Form zu einem Ankerpunkt einer anderen
|
||||
* Form.
|
||||
* <p>
|
||||
* Mit {@code buff} wird ein zusätzlicher Abstand angegeben, um den die Form
|
||||
* entlang des Ankerpunktes {@code anchor} verschoben wird.
|
||||
* <p>
|
||||
* Ist der Anker zum Beispiel {@code NORTH}, dann wird die Form um
|
||||
* {@code buff} nach oben verschoben.
|
||||
* {@code buff} oberhalb der oberen Kante der zweiten Form verschoben.
|
||||
* <p>
|
||||
* Befinden sich die Formen zuvor in folgender Ausrichtung:
|
||||
* <pre>
|
||||
* ┌─────────┐
|
||||
* │ │
|
||||
* W B │
|
||||
* ┌─────┐ │ │
|
||||
* │ │ └─────────┘
|
||||
* W A │
|
||||
* │ │
|
||||
* └─────┘
|
||||
* </pre>
|
||||
* <p>
|
||||
* bringt sie der Aufruf {@code B.moveTo(A, DOWN, 0)} in diese Ausrichtung:
|
||||
* <pre>
|
||||
* B.moveTo(A, WEST, 0) │ B.moveTo(A, WEST, 10)
|
||||
* │
|
||||
* ┌─────┬───┐ │ ┌┬────┬────┐
|
||||
* │ │ │ │ ││ │ │
|
||||
* │ A B│ │ │ ││ A B │
|
||||
* │ │ │ │ ││ │ │
|
||||
* └─────┴───┘ │ └┴────┴────┘
|
||||
* </pre>
|
||||
*
|
||||
* @param shape
|
||||
* @param dir
|
||||
* @param buff
|
||||
* @param shape Die andere Form.
|
||||
* @param dir Die Richtung des Ankerpunktes.
|
||||
* @param buff Der Abstand zum angegebenen Ankerpunkt.
|
||||
*/
|
||||
public void moveTo( Shape shape, Options.Direction dir, double buff ) {
|
||||
Point2D ap = shape.getAbsAnchorPoint(dir);
|
||||
@@ -406,15 +546,22 @@ public abstract class Shape extends BasicDrawable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Richtet die Form entlang der angegebenen Richtung am Rand der
|
||||
* Zeichenfläche aus.
|
||||
* Bewegt die Form an den Rand der Zeichenfläche in der angegebenen
|
||||
* Richtung.
|
||||
*
|
||||
* @param dir Die Richtung der Ausrichtung.
|
||||
* @param dir Die Richtung.
|
||||
*/
|
||||
public void alignTo( Options.Direction dir ) {
|
||||
alignTo(dir, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bewegt die Form mit dem angegebenen Abstand an den Rand der Zeichenfläche
|
||||
* in der angegebenen Richtung aus.
|
||||
*
|
||||
* @param dir Die Richtung.
|
||||
* @param buff Der Abstand zum Rand.
|
||||
*/
|
||||
public void alignTo( Options.Direction dir, double buff ) {
|
||||
Point2D anchorShape = Shape.getAnchorPoint(canvasWidth, canvasHeight, dir);
|
||||
Point2D anchorThis = this.getAbsAnchorPoint(dir);
|
||||
@@ -423,20 +570,58 @@ public abstract class Shape extends BasicDrawable {
|
||||
this.y += Math.abs(dir.y) * (anchorShape.getY() - anchorThis.getY()) + dir.y * buff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bewegt den Ankerpunkt dieser Form in der angegebenen Richtung zum
|
||||
* Gleichen Ankerpunkt der anderen Form.
|
||||
*
|
||||
* @param shape Die andere Form.
|
||||
* @param dir Die Richtung des Ankerpunktes.
|
||||
* @see #alignTo(Shape, Options.Direction, double)
|
||||
*/
|
||||
public void alignTo( Shape shape, Options.Direction dir ) {
|
||||
alignTo(shape, dir, 0.0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Richtet die Form entlang der angegebenen Richtung an einer anderen Form
|
||||
* aus. Für {@code DOWN} wird beispielsweise die y-Koordinate der unteren
|
||||
* Kante dieser Form an der unteren Kante der angegebenen Form {@code shape}
|
||||
* ausgerichtet. Die x-Koordinate wird nicht verändert. {@code buff} gibt
|
||||
* einen Abstand ab, um den diese From versetzt ausgerichtet werden soll.
|
||||
* aus.
|
||||
* <p>
|
||||
* {@code buff} gibt einen Abstand ab, um den diese From versetzt
|
||||
* ausgerichtet wird.
|
||||
* <p>
|
||||
* Für {@link #DOWN} wird beispielsweise die y-Koordinate der unteren Kante
|
||||
* dieser Form an der unteren Kante von {@code shape} ausgerichtet. Die
|
||||
* x-Koordinate wird in dem Fall nicht verändert.
|
||||
* <p>
|
||||
* Befinden sich die Formen beispielsweise in folgender Position:
|
||||
* <pre>
|
||||
* ┌─────┐
|
||||
* │ │
|
||||
* │ B │
|
||||
* ┌─────┐ │ │
|
||||
* │ │ └──D──┘
|
||||
* │ A │
|
||||
* │ │
|
||||
* └──D──┘
|
||||
* </pre>
|
||||
* <p>
|
||||
* <p>
|
||||
* werden sie durch {@code alignTo} so positioniert:
|
||||
* <pre>
|
||||
* B.alignTo(A, EAST, 0) │ B.alignTo(A, EAST, 10)
|
||||
* │
|
||||
* ┌─────┐ ┌─────┐ │ ┌─────┐
|
||||
* │ │ │ │ │ │ │ ┌─────┐
|
||||
* │ A │ │ B │ │ │ A │ │ │
|
||||
* │ │ │ │ │ │ │ │ B │
|
||||
* └──D──┘ └──D──┘ │ └──D──┘ │ │
|
||||
* │ └──D──┘
|
||||
* │
|
||||
* </pre>
|
||||
*
|
||||
* @param shape
|
||||
* @param dir
|
||||
* @param buff
|
||||
* @param shape Die andere Form.
|
||||
* @param dir Die Richtung.
|
||||
* @param buff Der Abstand.
|
||||
*/
|
||||
public void alignTo( Shape shape, Options.Direction dir, double buff ) {
|
||||
Point2D anchorShape = shape.getAbsAnchorPoint(dir);
|
||||
@@ -446,16 +631,46 @@ public abstract class Shape extends BasicDrawable {
|
||||
this.y += Math.abs(dir.y) * (anchorShape.getY() - anchorThis.getY()) + dir.y * buff;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shape
|
||||
* @param dir
|
||||
* @see #nextTo(Shape, Options.Direction, double)
|
||||
*/
|
||||
public void nextTo( Shape shape, Options.Direction dir ) {
|
||||
nextTo(shape, dir, DEFAULT_BUFFER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Bewegt die Form neben eine andere in Richtung des angegebenen
|
||||
* Ankerpunktes. Im Gegensatz zu
|
||||
* {@link #moveTo(Shape, Options.Direction, double)} wird die Breite bzw.
|
||||
* Höhe der Formen berücksichtigt und die Formen so platziert, dass keine
|
||||
* Überlappungen vorhanden sind.
|
||||
* Ankerpunktes.
|
||||
* <p>
|
||||
* Im Gegensatz zu {@link #moveTo(Shape, Options.Direction, double)} wird
|
||||
* die Breite bzw. Höhe der Formen berücksichtigt und die Formen so
|
||||
* platziert, dass keine Überlappungen vorhanden sind.
|
||||
* <p>
|
||||
* Befinden sich die Formen zuvor in folgender Ausrichtung:
|
||||
* <pre>
|
||||
* ┌─────┐
|
||||
* │ │
|
||||
* W B │
|
||||
* ┌──────┐ │ │
|
||||
* │ │ └─────┘
|
||||
* │ A E
|
||||
* │ │
|
||||
* └──────┘
|
||||
* </pre>
|
||||
* <p>
|
||||
* bringt sie der Aufruf {@code B.nextTo(A, EAST, 0)} in diese Ausrichtung:
|
||||
* <pre>
|
||||
* B.nextTo(A, EAST, 0) │ B.nextTo(A, EAST, 10)
|
||||
* │
|
||||
* ┌─────┬─────┐ │ ┌─────┐ ┌─────┐
|
||||
* │ │ │ │ │ │ │ │
|
||||
* │ A │ B │ │ │ A │ │ B │
|
||||
* │ │ │ │ │ │ │ │
|
||||
* └─────┴─────┘ │ └─────┘ └─────┘
|
||||
* │
|
||||
* </pre>
|
||||
*
|
||||
* @param shape
|
||||
* @param dir
|
||||
@@ -469,6 +684,19 @@ public abstract class Shape extends BasicDrawable {
|
||||
this.y += (anchorShape.getY() - anchorThis.getY()) + dir.y * buff;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGradient( schule.ngb.zm.Color from, schule.ngb.zm.Color to, Options.Direction dir ) {
|
||||
Point2D apDir = getAbsAnchorPoint(dir);
|
||||
Point2D apInv = getAbsAnchorPoint(dir.inverse());
|
||||
setGradient(apInv.getX(), apInv.getY(), from, apDir.getX(), apDir.getY(), to);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGradient( schule.ngb.zm.Color from, schule.ngb.zm.Color to ) {
|
||||
Point2D ap = getAbsAnchorPoint(CENTER);
|
||||
setGradient(ap.getX(), ap.getY(), Math.min(ap.getX(), ap.getY()), from, to);
|
||||
}
|
||||
|
||||
/*public void shear( double dx, double dy ) {
|
||||
verzerrung.shear(dx, dy);
|
||||
}*/
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Diese Paket enthält Formen, die Diagramme darstellen.
|
||||
*/
|
||||
package schule.ngb.zm.shapes.charts;
|
||||
13
src/main/java/schule/ngb/zm/shapes/package-info.java
Normal file
13
src/main/java/schule/ngb/zm/shapes/package-info.java
Normal file
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Dieses Paket enthält Implementationen der abstrakten
|
||||
* {@link schule.ngb.zm.shapes.Shape} Klasse.
|
||||
*
|
||||
* Jede Unterklasse von {@code Shape} stellt eine konkrete Form wie ein
|
||||
* {@link schule.ngb.zm.shapes.Rectangle Rechteck}, ein
|
||||
* {@link schule.ngb.zm.shapes.Circle Kreis} oder ein
|
||||
* {@link schule.ngb.zm.shapes.Picture Bild} dar.
|
||||
*
|
||||
* Mit {@link schule.ngb.zm.shapes.ShapeGroup} können Formen gruppiert
|
||||
* und gemeinsam transformiert werden.
|
||||
*/
|
||||
package schule.ngb.zm.shapes;
|
||||
@@ -19,7 +19,7 @@ import java.time.LocalDateTime;
|
||||
import java.time.ZoneOffset;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -28,21 +28,23 @@ import static java.lang.Math.log;
|
||||
import static schule.ngb.zm.Constants.random;
|
||||
|
||||
/**
|
||||
* Hilfsklasse, um zufällige Beispieldaten zu erzeugen.
|
||||
* Eine Helferklasse, um zufällige Beispieldaten zu erzeugen.
|
||||
* <p>
|
||||
* Die Klasse kann verschiedene Arten realistischer Beispieldaten erzeugen,
|
||||
* unter anderem Namen, E-Mail-Adressen, Passwörter oder Platzhalter-Bilder.
|
||||
* Die Klasse kann verschiedene Arten realistischer Beispieldaten erzeugen.
|
||||
* Unter anderem Namen, E-Mail-Adressen, Passwörter oder Platzhalter-Bilder.
|
||||
*/
|
||||
@SuppressWarnings( "unused" )
|
||||
public final class Faker {
|
||||
|
||||
/**
|
||||
* URL, von der extern generierte Fake-Bilder geladen werden können.
|
||||
* <p>
|
||||
* Die URL wird als Format-String definiert mit zwei {@code %d}
|
||||
* Platzhaltern, die durch die Breite und Höhe des gewünschten Bildes
|
||||
* ersetzt werden.
|
||||
*/
|
||||
public static final String FAKE_IMG_URL = "https://loremflickr.com/%d/%d";
|
||||
|
||||
public static void main( String[] args ) {
|
||||
String text = Faker.fakeText(2000, 8);
|
||||
System.out.println(text);
|
||||
}
|
||||
|
||||
/**
|
||||
* Erzeugt ein Array mit den angegebenen Anzahl zufälliger Benutzerdaten.
|
||||
* <p>
|
||||
@@ -76,8 +78,8 @@ public final class Faker {
|
||||
|
||||
|
||||
/**
|
||||
* Erzeugt ein Array mit den angegebenen Anzahl zufälliger Namen (Vor- und
|
||||
* Nachname).
|
||||
* Erzeugt ein Array mit den angegebenen Anzahl zufälliger Namen im Format
|
||||
* "Vorname Nachname".
|
||||
*
|
||||
* @param count Anzahl der Beispieldaten.
|
||||
* @return Ein Array mit den Beispieldaten.
|
||||
@@ -133,7 +135,7 @@ public final class Faker {
|
||||
|
||||
/**
|
||||
* Erzeugt ein Array mit den angegebenen Anzahl zufälliger
|
||||
* {@code Date}-Objekte.
|
||||
* {@code LocalDate}-Objekte, die ein Datum ohne Uhrzeit beschreiben.
|
||||
*
|
||||
* @param count Anzahl der Beispieldaten.
|
||||
* @return Ein Array mit den Beispieldaten.
|
||||
@@ -151,6 +153,14 @@ public final class Faker {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erzeugt ein Array mit den angegebenen Anzahl zufälliger
|
||||
* {@code LocalDateTime}-Objekte, die einen Zeitpunkt mit Dateum und Uhrzeit
|
||||
* beschreiben,
|
||||
*
|
||||
* @param count Anzahl der Beispieldaten.
|
||||
* @return Ein Array mit den Beispieldaten.
|
||||
*/
|
||||
public static LocalDateTime[] fakeDatetimes( int count ) {
|
||||
long nowEpoch = LocalDateTime.now().toEpochSecond(ZoneOffset.UTC);
|
||||
long from = LocalDateTime.ofEpochSecond(nowEpoch - 18 * 365, 0, ZoneOffset.UTC).toEpochSecond(ZoneOffset.UTC);
|
||||
@@ -164,6 +174,17 @@ public final class Faker {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erzeugt einen Blindtext mit der angegebenen Anzahl Worten, aufgeteilt in
|
||||
* die angegebene Anzahl Absätze.
|
||||
* <p>
|
||||
* Abssätze werden duch einen doppelten Zeilenumbruch {@code \n\n}
|
||||
* getrennt.
|
||||
*
|
||||
* @param words Anzahl Wörter im Text insgesamt.
|
||||
* @param paragraphs Anzahl Absätze.
|
||||
* @return Ein zufälliger Blindtext.
|
||||
*/
|
||||
public static String fakeText( int words, int paragraphs ) {
|
||||
String basetext = "";
|
||||
try(
|
||||
@@ -197,6 +218,16 @@ public final class Faker {
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erzeugt ein Array mit der angegebenen Anzahl zufällig erzeugter Integer
|
||||
* im angegebenen Bereich.
|
||||
*
|
||||
* @param count Anzahl der Zahlen im Array.
|
||||
* @param min Untere Grenze der Zufallszahlen.
|
||||
* @param max Obere Grenze der Zufallszahlen.
|
||||
* @return Ein Array mit Zufallszahlen.
|
||||
* @see Constants#random(int, int)
|
||||
*/
|
||||
public static int[] fakeIntArray( int count, int min, int max ) {
|
||||
int[] arr = new int[count];
|
||||
for( int i = 0; i < count; i++ ) {
|
||||
@@ -205,14 +236,56 @@ public final class Faker {
|
||||
return arr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erzeugt eine Liste mit der angegebenen Anzahl zufällig erzeugter Integer
|
||||
* im angegebenen Bereich.
|
||||
* <p>
|
||||
* Ist {@code list} ein Listenobjekt, werden dei Zahlen an diese angehängt.
|
||||
* Wird {@code null} übergeben, wird eine neue {@link ArrayList} erzeugt.
|
||||
*
|
||||
* @param count Anzahl der erzeugten Zahlen.
|
||||
* @param min Untere Grenze der Zufallszahlen.
|
||||
* @param max Obere Grenze der Zufallszahlen.
|
||||
* @param list Eine Liste, die befüllt werden soll, oder {@code null}.
|
||||
* @return Ein Array mit Zufallszahlen.
|
||||
* @see Constants#random(int, int)
|
||||
*/
|
||||
public static List<Integer> fakeIntegerList( int count, int min, int max, List<Integer> list ) {
|
||||
if( list == null ) {
|
||||
list = new ArrayList<>(count);
|
||||
List<Integer> result = (list == null) ? new ArrayList<>(count) : list;
|
||||
fakeIntegers(count, min, max, result::add);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Erzeugt die angegebene Anzahl Zufallszahlen im angegebenen Bereich und
|
||||
* übergibt sie an den angegebenen {@code Consumer}.
|
||||
*
|
||||
* Ein typischer Aufruf, um eine {@code #LinkedList} mit 100 Zufallszahlen
|
||||
* zu erzeugen könnte so aussehen:
|
||||
* <pre><code>
|
||||
* List<Integer> l = new LinkedList<>();
|
||||
* Faker.fakeIntegers(100, 0, 100, l::add);
|
||||
* </code></pre>
|
||||
*
|
||||
* @param count Anzahl der erzeugten Zahlen.
|
||||
* @param min Untere Grenze der Zufallszahlen.
|
||||
* @param max Obere Grenze der Zufallszahlen.
|
||||
* @param con {@code Consumer} für die Zahlen.
|
||||
*/
|
||||
public static void fakeIntegers( int count, int min, int max, Consumer<Integer> con ) {
|
||||
for( int i = 0; i < count; i++ ) {
|
||||
list.add(random(min, max));
|
||||
con.accept(random(min, max));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public static <L> L fakeIntegers( int count, int min, int max, Supplier<L> sup, BiConsumer<L, Integer> con ) {
|
||||
L result = sup.get();
|
||||
|
||||
for( int i = 0; i < count; i++ ) {
|
||||
con.accept(result, random(min, max));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings( "unchecked" )
|
||||
|
||||
@@ -77,7 +77,7 @@ public final class Log {
|
||||
* mindestens herabgesenkt werden sollen.
|
||||
*/
|
||||
public static void enableGlobalLevel( Level level ) {
|
||||
int lvl = Validator.requireNotNull(level).intValue();
|
||||
int lvl = Validator.requireNotNull(level, "level").intValue();
|
||||
ensureRootLoggerInitialized();
|
||||
|
||||
// Decrease level of root level ConsoleHandlers for output
|
||||
|
||||
@@ -6,35 +6,55 @@ import java.util.function.Supplier;
|
||||
/**
|
||||
* Statische Methoden, um Methodenparameter auf Gültigkeit zu prüfen.
|
||||
*/
|
||||
@SuppressWarnings( "UnusedReturnValue" )
|
||||
@SuppressWarnings( {"unused", "UnusedReturnValue"} )
|
||||
public class Validator {
|
||||
|
||||
public static final <T> T requireNotNull( T obj ) {
|
||||
return Objects.requireNonNull(obj);
|
||||
public static final <T> T requireNotNull( T obj, CharSequence paramName ) {
|
||||
return requireNotNull(obj, () -> "Parameter <%s> may not be null.".format(paramName.toString()));
|
||||
}
|
||||
|
||||
public static final <T> T requireNotNull( T obj, CharSequence msg ) {
|
||||
return Objects.requireNonNull(obj, msg::toString);
|
||||
public static final <T> T requireNotNull( T obj, CharSequence paramName, CharSequence msg ) {
|
||||
return requireNotNull(obj, () -> msg.toString().format(paramName.toString()));
|
||||
}
|
||||
|
||||
public static final <T> T requireNotNull( T obj, Supplier<String> msg ) {
|
||||
return Objects.requireNonNull(obj, msg);
|
||||
if( obj == null ) {
|
||||
throw new NullPointerException(msg == null ? "Parameter may nut be null." : msg.get());
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static final String requireNotEmpty( String str ) {
|
||||
return requireNotEmpty(str, (Supplier<String>) null);
|
||||
public static final String requireNotEmpty( String str, CharSequence paramName ) {
|
||||
return requireNotEmpty(str, () -> String.format("Parameter <%s> may not be empty string (<%s> provided)", paramName, str));
|
||||
}
|
||||
|
||||
public static final String requireNotEmpty( String str, CharSequence msg ) {
|
||||
return requireNotEmpty(str, msg::toString);
|
||||
public static final String requireNotEmpty( String str, CharSequence paramName, CharSequence msg ) {
|
||||
return requireNotEmpty(str, () -> msg.toString().format(paramName.toString()));
|
||||
}
|
||||
|
||||
public static final String requireNotEmpty( String str, Supplier<String> msg ) {
|
||||
if( str.isEmpty() )
|
||||
if( str.isEmpty() ) {
|
||||
throw new IllegalArgumentException(msg == null ? String.format("Parameter may not be empty string (<%s> provided)", str) : msg.get());
|
||||
}
|
||||
return str;
|
||||
}
|
||||
|
||||
public static final <T> T[] requireNotEmpty( T[] arr, CharSequence paramName ) {
|
||||
return requireNotEmpty(arr, () -> String.format("Parameter <%s> may not be empty", paramName));
|
||||
}
|
||||
|
||||
public static final <T> T[] requireNotEmpty( T[] arr, CharSequence paramName, CharSequence msg ) {
|
||||
return requireNotEmpty(arr, () -> msg.toString().format(paramName.toString()));
|
||||
}
|
||||
|
||||
public static final <T> T[] requireNotEmpty( T[] arr, Supplier<String> msg ) {
|
||||
if( arr.length == 0 )
|
||||
throw new IllegalArgumentException(msg == null ? "Parameter array may not be empty" : msg.get());
|
||||
return arr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static final int requirePositive( int i ) {
|
||||
return requirePositive(i, (Supplier<String>) null);
|
||||
}
|
||||
@@ -139,21 +159,6 @@ public class Validator {
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
public static final <T> T[] requireNotEmpty( T[] arr ) {
|
||||
return requireNotEmpty(arr, (Supplier<String>) null);
|
||||
}
|
||||
|
||||
public static final <T> T[] requireNotEmpty( T[] arr, CharSequence msg ) {
|
||||
return requireNotEmpty(arr, msg::toString);
|
||||
}
|
||||
|
||||
public static final <T> T[] requireNotEmpty( T[] arr, Supplier<String> msg ) {
|
||||
if( arr.length == 0 )
|
||||
throw new IllegalArgumentException(msg == null ? "Parameter array may not be empty" : msg.get());
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static final <T> T[] requireSize( T[] arr, int size ) {
|
||||
return requireSize(arr, size, (Supplier<String>) null);
|
||||
}
|
||||
@@ -168,20 +173,6 @@ public class Validator {
|
||||
return arr;
|
||||
}
|
||||
|
||||
public static final <T> T[] requireValid( T[] arr ) {
|
||||
return requireValid(arr, (Supplier<String>) null);
|
||||
}
|
||||
|
||||
public static final <T> T[] requireValid( T[] arr, CharSequence msg ) {
|
||||
return requireValid(arr, msg::toString);
|
||||
}
|
||||
|
||||
public static final <T> T[] requireValid( T[] arr, Supplier<String> msg ) {
|
||||
if( arr == null || arr.length > 0 )
|
||||
throw new IllegalArgumentException(msg == null ? "Parameter array may not be null or empty" : msg.get());
|
||||
return arr;
|
||||
}
|
||||
|
||||
private Validator() {
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,9 @@ import java.util.function.BiConsumer;
|
||||
* dispatcher.dispatchEvent("stop", new MyEvent());
|
||||
* }
|
||||
* </code></pre>
|
||||
* <p>
|
||||
* Siehe {@link schule.ngb.zm.media.AudioListener} und
|
||||
* {@link schule.ngb.zm.media.Music} für ein Beispiel der Verwendung.
|
||||
*
|
||||
* @param <E> Typ der Event-Objekte.
|
||||
* @param <L> Typ der verwendeten Listener-Schnittstelle.
|
||||
@@ -73,8 +76,8 @@ public class EventDispatcher<E, L extends Listener<E>> {
|
||||
}
|
||||
|
||||
public void registerEventType( String eventKey, BiConsumer<E, L> dispatcher ) {
|
||||
Validator.requireNotNull(eventKey);
|
||||
Validator.requireNotNull(dispatcher);
|
||||
Validator.requireNotNull(eventKey, "eventKey");
|
||||
Validator.requireNotNull(dispatcher, "dispatcher");
|
||||
|
||||
if( !eventRegistered(eventKey) ) {
|
||||
eventRegistry.put(eventKey, dispatcher);
|
||||
@@ -89,7 +92,7 @@ public class EventDispatcher<E, L extends Listener<E>> {
|
||||
listeners.remove(listener);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@SuppressWarnings( "unused" )
|
||||
public boolean hasListeners() {
|
||||
return !listeners.isEmpty();
|
||||
}
|
||||
@@ -99,8 +102,8 @@ public class EventDispatcher<E, L extends Listener<E>> {
|
||||
}
|
||||
|
||||
public void dispatchEvent( String eventKey, final E event ) {
|
||||
Validator.requireNotNull(eventKey);
|
||||
Validator.requireNotNull(event);
|
||||
Validator.requireNotNull(eventKey, "eventKey");
|
||||
Validator.requireNotNull(event, "event");
|
||||
|
||||
if( eventRegistered(eventKey) ) {
|
||||
final BiConsumer<E, L> dispatcher = eventRegistry.get(eventKey);
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Dieses Paket enthält Helferklassen, die das Listener-Entwurfsmuster
|
||||
* umsetzen.
|
||||
*/
|
||||
package schule.ngb.zm.util.events;
|
||||
@@ -5,14 +5,21 @@ import schule.ngb.zm.util.Validator;
|
||||
|
||||
import java.awt.Font;
|
||||
import java.awt.FontFormatException;
|
||||
import java.awt.Image;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Eine Helferklasse mit Klassenmethoden, um Schriftarten zu laden.
|
||||
* <p>
|
||||
* Schriftarten können von verschiedenen Quellen geladen werden. Schriftarten,
|
||||
* die aus Dateien geladen wurden, werden in einem internen Cache gespeichert
|
||||
* und nachfolgende Versuche, dieselbe Schriftart zu laden, werden aus dem Cache
|
||||
* bedient.
|
||||
*/
|
||||
public class FontLoader {
|
||||
|
||||
private static final Map<String, Font> fontCache = new ConcurrentHashMap<>();
|
||||
@@ -22,11 +29,12 @@ public class FontLoader {
|
||||
* <p>
|
||||
* Die Methode kann eine Liste von Schriften bekommen und probiert diese
|
||||
* nacheinander zu laden. Die erste Schrift, die Fehlerfrei geladen werden
|
||||
* kann, wird zurückgegeben. Kann keine der Schriften geladen werden, ist das
|
||||
* Ergebnis {@code null}.
|
||||
* kann, wird zurückgegeben. Kann keine der Schriften geladen werden, ist
|
||||
* das Ergebnis {@code null}.
|
||||
* <p>
|
||||
* Die gefundene Schrift wird unter ihrem Dateinamen in den Schriftenspeicher
|
||||
* geladen und kann danach in der Zeichenmaschine benutzt werden.
|
||||
* Die gefundene Schrift wird unter ihrem Dateinamen in den
|
||||
* Schriftenspeicher geladen und kann danach in der Zeichenmaschine benutzt
|
||||
* werden.
|
||||
* <p>
|
||||
* Eine Datei mit dem Namen "fonts/Font-Name.ttf" würde mit dem Namen
|
||||
* "Font-Name" geladen und kann danach zum Beispiel in einem
|
||||
@@ -53,7 +61,7 @@ public class FontLoader {
|
||||
}
|
||||
|
||||
public static Font loadFont( String name, String source ) {
|
||||
Validator.requireNotNull(source,"Font source may not be null");
|
||||
Validator.requireNotNull(source, "Font source may not be null");
|
||||
Validator.requireNotEmpty(source, "Font source may not be empty.");
|
||||
|
||||
if( fontCache.containsKey(name) ) {
|
||||
@@ -96,11 +104,12 @@ public class FontLoader {
|
||||
* <p>
|
||||
* Die Methode kann eine Liste von Schriften bekommen und probiert diese
|
||||
* nacheinander zu laden. Die erste Schrift, die Fehlerfrei geladen werden
|
||||
* kann, wird zurückgegeben. Kann keine der Schriften geladen werden, ist das
|
||||
* Ergebnis {@code null}.
|
||||
* kann, wird zurückgegeben. Kann keine der Schriften geladen werden, ist
|
||||
* das Ergebnis {@code null}.
|
||||
* <p>
|
||||
* Die gefundene Schrift wird unter ihrem Dateinamen in den Schriftenspeicher
|
||||
* geladen und kann danach in der Zeichenmaschine benutzt werden.
|
||||
* Die gefundene Schrift wird unter ihrem Dateinamen in den
|
||||
* Schriftenspeicher geladen und kann danach in der Zeichenmaschine benutzt
|
||||
* werden.
|
||||
* <p>
|
||||
* Eine Datei mit dem Namen "fonts/Font-Name.ttf" würde mit dem Namen
|
||||
* "Font-Name" geladen und kann danach zum Beispiel in einem
|
||||
@@ -113,7 +122,7 @@ public class FontLoader {
|
||||
* @see #loadFont(String, String)
|
||||
*/
|
||||
public static Font loadFonts( String name, String... sources ) {
|
||||
for( String fontSource: sources ) {
|
||||
for( String fontSource : sources ) {
|
||||
// TODO: Ignore exceptions in this case and throw own at end?
|
||||
Font font = loadFont(name, fontSource);
|
||||
if( font != null ) {
|
||||
|
||||
@@ -18,6 +18,13 @@ import java.lang.ref.SoftReference;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Eine Helferklasse mit Klassenmethoden, um Bilder zu laden.
|
||||
* <p>
|
||||
* Bilder können von verschiedenen Quellen als {@link Image} geladen werden. Die
|
||||
* Objekte werden in einem internen Cache gespeichert und nachfolgende Versuche,
|
||||
* dieselbe Quelle zu laden, werden aus dem Cache bedient.
|
||||
*/
|
||||
public final class ImageLoader {
|
||||
|
||||
public static boolean caching = true;
|
||||
|
||||
5
src/main/java/schule/ngb/zm/util/io/package-info.java
Normal file
5
src/main/java/schule/ngb/zm/util/io/package-info.java
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Dieses Paket enthält Helferklassen, um Ressourcen aus verschiedenen Quellen
|
||||
* zu laden.
|
||||
*/
|
||||
package schule.ngb.zm.util.io;
|
||||
4
src/main/java/schule/ngb/zm/util/package-info.java
Normal file
4
src/main/java/schule/ngb/zm/util/package-info.java
Normal file
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Dieses Paket enthält Helferklassen für verschiedene Einsatzzwecke.
|
||||
*/
|
||||
package schule.ngb.zm.util;
|
||||
5
src/main/java/schule/ngb/zm/util/tasks/package-info.java
Normal file
5
src/main/java/schule/ngb/zm/util/tasks/package-info.java
Normal file
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Dieses Paket enthält Helferklassen zur Verarbeitung paralleler Aufgaben
|
||||
* innerhalb der Zeichenmaschine.
|
||||
*/
|
||||
package schule.ngb.zm.util.tasks;
|
||||
@@ -10,6 +10,11 @@ import java.awt.Shape;
|
||||
import java.awt.Stroke;
|
||||
import java.util.LinkedList;
|
||||
|
||||
/**
|
||||
* Eine Ebene, die {@link java.awt.Shape} Objekte zeichnet.
|
||||
*
|
||||
* Die Ebene ist für Tests der Kompatibilität mit Java-AWT gedacht.
|
||||
*/
|
||||
@SuppressWarnings( "unused" )
|
||||
public final class Shape2DLayer extends Layer {
|
||||
|
||||
31
src/test/java/schule/ngb/zm/util/FakerTest.java
Normal file
31
src/test/java/schule/ngb/zm/util/FakerTest.java
Normal file
@@ -0,0 +1,31 @@
|
||||
package schule.ngb.zm.util;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import schule.ngb.zm.util.abi.List;
|
||||
import schule.ngb.zm.util.abi.Queue;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class FakerTest {
|
||||
|
||||
@Test
|
||||
void fakeIntegers() {
|
||||
LinkedList<Integer> l = new LinkedList<>();
|
||||
Faker.fakeIntegers(100, 0, 100, l::add);
|
||||
assertEquals(100, l.size());
|
||||
|
||||
LinkedList<Integer> intList = Faker.fakeIntegers(100, 0, 100, LinkedList::new, (list, i) -> list.add(i));
|
||||
assertEquals(100, intList.size());
|
||||
|
||||
List<Integer> abiList = Faker.fakeIntegers(100, 0, 100, List::new, (list, i) -> list.append(i));
|
||||
assertFalse(abiList.isEmpty());
|
||||
|
||||
Queue<Integer> abiQueue = new Queue<>();
|
||||
Faker.fakeIntegers(100, 0, 100, abiQueue::enqueue);
|
||||
assertFalse(abiQueue.isEmpty());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,14 +11,14 @@ class ValidatorTest {
|
||||
StringBuilder sb = new StringBuilder("Message");
|
||||
|
||||
Object o1 = new Object();
|
||||
assertEquals(o1, Validator.requireNotNull(o1));
|
||||
assertEquals(o1, Validator.requireNotNull(o1, "Message"));
|
||||
assertEquals(o1, Validator.requireNotNull(o1, sb));
|
||||
assertEquals(o1, Validator.requireNotNull(o1, "content"));
|
||||
assertEquals(o1, Validator.requireNotNull(o1, "content", "Message"));
|
||||
assertEquals(o1, Validator.requireNotNull(o1, "content", sb));
|
||||
assertEquals(o1, Validator.requireNotNull(o1, ()->"Message"));
|
||||
|
||||
String o2 = null;
|
||||
assertThrowsExactly(NullPointerException.class, () -> Validator.requireNotNull(o2));
|
||||
assertThrowsExactly(NullPointerException.class, () -> Validator.requireNotNull(o2, "Message"));
|
||||
assertThrowsExactly(NullPointerException.class, () -> Validator.requireNotNull(o2, "content"));
|
||||
assertThrowsExactly(NullPointerException.class, () -> Validator.requireNotNull(o2, "content", "Message"));
|
||||
assertThrowsExactly(NullPointerException.class, () -> Validator.requireNotNull(o2, ()->"Message"));
|
||||
}
|
||||
|
||||
@@ -27,14 +27,14 @@ class ValidatorTest {
|
||||
StringBuilder sb = new StringBuilder("Message");
|
||||
|
||||
String s1 = "Content";
|
||||
assertEquals(s1, Validator.requireNotEmpty(s1));
|
||||
assertEquals(s1, Validator.requireNotEmpty(s1, "Message"));
|
||||
assertEquals(s1, Validator.requireNotEmpty(s1, sb));
|
||||
assertEquals(s1, Validator.requireNotEmpty(s1, "content"));
|
||||
assertEquals(s1, Validator.requireNotEmpty(s1, "content", "Message"));
|
||||
assertEquals(s1, Validator.requireNotEmpty(s1, "content", sb));
|
||||
assertEquals(s1, Validator.requireNotEmpty(s1, ()->"Message"));
|
||||
|
||||
String s2 = "";
|
||||
assertThrowsExactly(IllegalArgumentException.class, () -> Validator.requireNotEmpty(s2));
|
||||
assertThrowsExactly(IllegalArgumentException.class, () -> Validator.requireNotEmpty(s2, "Message"));
|
||||
assertThrowsExactly(IllegalArgumentException.class, () -> Validator.requireNotEmpty(s2, "content"));
|
||||
assertThrowsExactly(IllegalArgumentException.class, () -> Validator.requireNotEmpty(s2, "content", "Message"));
|
||||
assertThrowsExactly(IllegalArgumentException.class, () -> Validator.requireNotEmpty(s2, ()->"Message"));
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user