diff --git a/.gitignore b/.gitignore index ece0a1b..d1c7eb1 100644 --- a/.gitignore +++ b/.gitignore @@ -32,3 +32,19 @@ hs_err_pid* .DS_Store ._* Thumbs.db + +.gradle +**/build/ +!src/**/build/ + +# Ignore Gradle GUI config +gradle-app.setting + +# Avoid ignoring Gradle wrapper jar file (.jar files are usually ignored) +!gradle-wrapper.jar + +# Avoid ignore Gradle wrappper properties +!gradle-wrapper.properties + +# Cache of project +.gradletasknamecache diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..823567a --- /dev/null +++ b/build.gradle @@ -0,0 +1,46 @@ +plugins { + id 'idea' + id 'java-library' +} + +/*properties { + zmVersion { + major = 0; + minor = 0; + rev = 21; + } +}*/ + +group 'schule.ngb' +version '0.0.21-SNAPSHOT' +//version '{$zmVersion.major}.{$zmVersion.minor}.{$zmVersion.rev}-SNAPSHOT' + +compileJava { + options.release = 11 +} + +repositories { + mavenCentral() +} + +dependencies { + runtimeOnly 'com.googlecode.soundlibs:jlayer:1.0.1.4' + runtimeOnly 'com.googlecode.soundlibs:tritonus-share:0.3.7.4' + runtimeOnly 'com.googlecode.soundlibs:mp3spi:1.9.5.4' + + testImplementation 'org.junit.jupiter:junit-jupiter-api:5.8.1' + testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1' +} + +test { + useJUnitPlatform() +} + +tasks.register('jarMP3SPI', Jar) { + archiveClassifier = 'all' + duplicatesStrategy = 'exclude' + archivesBaseName = 'zeichenmaschine-mp3spi' + from { + configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } + } +} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar new file mode 100644 index 0000000..41d9927 Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 0000000..41dfb87 --- /dev/null +++ b/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,5 @@ +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists diff --git a/gradlew b/gradlew new file mode 100755 index 0000000..1b6c787 --- /dev/null +++ b/gradlew @@ -0,0 +1,234 @@ +#!/bin/sh + +# +# Copyright © 2015-2021 the original authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +############################################################################## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# +############################################################################## + +# Attempt to set APP_HOME + +# Resolve links: $0 may be a link +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac +done + +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit + +APP_NAME="Gradle" +APP_BASE_NAME=${0##*/} + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Use the maximum available, or set MAX_FD != -1 to use that value. +MAX_FD=maximum + +warn () { + echo "$*" +} >&2 + +die () { + echo + echo "$*" + echo + exit 1 +} >&2 + +# OS specific support (must be 'true' or 'false'). +cygwin=false +msys=false +darwin=false +nonstop=false +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; +esac + +CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + + +# Determine the Java command to use to start the JVM. +if [ -n "$JAVA_HOME" ] ; then + if [ -x "$JAVA_HOME/jre/sh/java" ] ; then + # IBM's JDK on AIX uses strange locations for the executables + JAVACMD=$JAVA_HOME/jre/sh/java + else + JAVACMD=$JAVA_HOME/bin/java + fi + if [ ! -x "$JAVACMD" ] ; then + die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." + fi +else + JAVACMD=java + which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + +Please set the JAVA_HOME variable in your environment to match the +location of your Java installation." +fi + +# Increase the maximum file descriptors if we can. +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac +fi + +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. + +# For Cygwin or MSYS, switch paths to Windows format before running java +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + + # Now convert the arguments - kludge to limit ourselves to /bin/sh + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) + fi + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg + done +fi + +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# + +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' + +exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat new file mode 100644 index 0000000..ac1b06f --- /dev/null +++ b/gradlew.bat @@ -0,0 +1,89 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + +@if "%DEBUG%" == "" @echo off +@rem ########################################################################## +@rem +@rem Gradle startup script for Windows +@rem +@rem ########################################################################## + +@rem Set local scope for the variables with windows NT shell +if "%OS%"=="Windows_NT" setlocal + +set DIRNAME=%~dp0 +if "%DIRNAME%" == "" set DIRNAME=. +set APP_BASE_NAME=%~n0 +set APP_HOME=%DIRNAME% + +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + +@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" + +@rem Find java.exe +if defined JAVA_HOME goto findJavaFromJavaHome + +set JAVA_EXE=java.exe +%JAVA_EXE% -version >NUL 2>&1 +if "%ERRORLEVEL%" == "0" goto execute + +echo. +echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:findJavaFromJavaHome +set JAVA_HOME=%JAVA_HOME:"=% +set JAVA_EXE=%JAVA_HOME%/bin/java.exe + +if exist "%JAVA_EXE%" goto execute + +echo. +echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% +echo. +echo Please set the JAVA_HOME variable in your environment to match the +echo location of your Java installation. + +goto fail + +:execute +@rem Setup the command line + +set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + + +@rem Execute Gradle +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* + +:end +@rem End local scope for the variables with windows NT shell +if "%ERRORLEVEL%"=="0" goto mainEnd + +:fail +rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of +rem the _cmd.exe /c_ return code! +if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 +exit /b 1 + +:mainEnd +if "%OS%"=="Windows_NT" endlocal + +:omega diff --git a/settings.gradle b/settings.gradle new file mode 100644 index 0000000..fb84f31 --- /dev/null +++ b/settings.gradle @@ -0,0 +1,2 @@ +rootProject.name = 'zeichenmaschine' + diff --git a/src/schule/ngb/zm/Color.java b/src/main/java/schule/ngb/zm/Color.java similarity index 91% rename from src/schule/ngb/zm/Color.java rename to src/main/java/schule/ngb/zm/Color.java index e858806..33c2033 100644 --- a/src/schule/ngb/zm/Color.java +++ b/src/main/java/schule/ngb/zm/Color.java @@ -3,12 +3,12 @@ package schule.ngb.zm; /** * Repräsentiert eine Farbe in der Zeichenmaschine. *

- * Farben bestehen entweder aus einem Grauwert (zwischen 0 und - * 255) oder einem Rot-, Grün- und Blauanteil (jeweils zwischen - * 0 und 255). + * Farben bestehen entweder aus einem Grauwert (zwischen 0 und + * 255) oder einem Rot-, Grün- und Blauanteil (jeweils zwischen + * 0 und 255). *

- * Eine Farbe hat außerdem einen Transparenzwert zwischen 0 - * (unsichtbar) und 255 (deckend). + * Eine Farbe hat außerdem einen Transparenzwert zwischen 0 + * (unsichtbar) und 255 (deckend). */ public class Color { @@ -106,7 +106,7 @@ public class Color { /** * Erstellt eine graue Farbe entsprechend des Grauwertes gray. * - * @param gray Ein Grauwert zwischen 0 und 255. + * @param gray Ein Grauwert zwischen 0 und 255. */ public Color( int gray ) { this(gray, gray, gray, 255); @@ -116,7 +116,7 @@ public class Color { * Erstellt eine graue Farbe entsprechend des Grauwertes gray und * des Transparentwertes alpha. * - * @param gray Ein Grauwert zwischen 0 und 255. + * @param gray Ein Grauwert zwischen 0 und 255. */ public Color( int gray, int alpha ) { this(gray, gray, gray, alpha); @@ -125,12 +125,11 @@ public class Color { /** * Erstellt eine Farbe. Die Parameter red, green und * blue geben die Rot-, Grün- und Blauanteile der Farbe. Die Werte - * liegen zwischen 0 und 255. + * liegen zwischen 0 und 255. * - * @param red Rotwert zwischen 0 und 255. - * @param green Grünwert zwischen 0 und 255. - * @param blue Blauwert zwischen 0 und 255. - * @return Ein passendes Farbobjekt. + * @param red Rotwert zwischen 0 und 255. + * @param green Grünwert zwischen 0 und 255. + * @param blue Blauwert zwischen 0 und 255. */ public Color( int red, int green, int blue ) { this(red, green, blue, 255); @@ -139,17 +138,16 @@ public class Color { /** * Erstellt eine Farbe. Die Parameter red, green und * blue geben die Rot-, Grün- und Blauanteile der Farbe. Die Werte - * liegen zwischen 0 und 255. + * liegen zwischen 0 und 255. * alpha gibt den den Transparentwert an (auch zwischen - * code>0 und 255), wobei - * 0 komplett durchsichtig ist und 255 komplett + * 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. - * @param blue Blauwert zwischen 0 und 255. - * @param alpha Transparentwert zwischen 0 und 255. - * @return Ein passendes Farbobjekt. + * @param red Rotwert zwischen 0 und 255. + * @param green Grünwert zwischen 0 und 255. + * @param blue Blauwert zwischen 0 und 255. + * @param alpha Transparentwert zwischen 0 und 255. */ public Color( int red, int green, int blue, int alpha ) { rgba = (alpha << 24) | (red << 16) | (green << 8) | blue; @@ -239,7 +237,7 @@ public class Color { /** * Erzeugt eine Farbe aus einem hexadezimalen Code. Der Hexcode kann * sechs- oder achtstellig sein (wenn ein Transparentwert vorhanden ist). - * Dem Code kann ein # Zeichen vorangestellt sein. + * Dem Code kann ein {@code #} Zeichen vorangestellt sein. * * @param hexcode * @return diff --git a/src/schule/ngb/zm/ColorLayer.java b/src/main/java/schule/ngb/zm/ColorLayer.java similarity index 100% rename from src/schule/ngb/zm/ColorLayer.java rename to src/main/java/schule/ngb/zm/ColorLayer.java diff --git a/src/schule/ngb/zm/Constants.java b/src/main/java/schule/ngb/zm/Constants.java similarity index 93% rename from src/schule/ngb/zm/Constants.java rename to src/main/java/schule/ngb/zm/Constants.java index bde0492..561b3aa 100644 --- a/src/schule/ngb/zm/Constants.java +++ b/src/main/java/schule/ngb/zm/Constants.java @@ -387,10 +387,10 @@ public class Constants { /** * Erstellt eine graue Farbe. Der Parameter {@code gray} gibt einen Grauwert - * zwischen 0 und 255 an, wobei - * 0 schwarz und 255 weiß ist. + * zwischen 0 und 255 an, wobei + * 0 schwarz und 255 weiß ist. * - * @param gray Grauwert zwischen 0 und 255. + * @param gray Grauwert zwischen 0 und 255. * @return Ein passendes Farbobjekt. */ public static final Color color( int gray ) { @@ -399,16 +399,16 @@ public class Constants { /** * Erstellt eine graue Farbe. Der Parameter {@code gray} gibt einen Grauwert - * zwischen 0 und 255 an, wobei - * 0 schwarz und 255 weiß ist. + * zwischen 0 und 255 an, wobei + * 0 schwarz und 255 weiß ist. * {@code alpha} gibt den den Transparentwert an (auch zwischen - * 0 und 255), wobei - * 0 komplett durchsichtig ist und 255 komplett + * 0 und 255), wobei + * 0 komplett durchsichtig ist und 255 komplett * deckend. * - * @param gray Grauwert zwischen 0 und 255. - * @param alpha Transparentwert zwischen 0 und - * 255. + * @param gray Grauwert zwischen 0 und 255. + * @param alpha Transparentwert zwischen 0 und + * 255. * @return Ein passendes Farbobjekt. */ public static final Color color( int gray, int alpha ) { @@ -418,11 +418,11 @@ public class Constants { /** * 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. + * liegen zwischen 0 und 255. * - * @param red Rotwert zwischen 0 und 255. - * @param green Grünwert zwischen 0 und 255. - * @param blue Blauwert zwischen 0 und 255. + * @param red Rotwert zwischen 0 und 255. + * @param green Grünwert zwischen 0 und 255. + * @param blue Blauwert zwischen 0 und 255. * @return Ein passendes Farbobjekt. */ public static final Color color( int red, int green, int blue ) { @@ -432,17 +432,17 @@ public class Constants { /** * 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 code>0 und - * 255), wobei - * 0 komplett durchsichtig ist und 255 komplett + * 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. - * @param blue Blauwert zwischen 0 und 255. - * @param alpha Transparenzwert zwischen 0 und - * 255. + * @param red Rotwert zwischen 0 und 255. + * @param green Grünwert zwischen 0 und 255. + * @param blue Blauwert zwischen 0 und 255. + * @param alpha Transparenzwert zwischen 0 und + * 255. * @return Ein passendes Farbobjekt. */ public static final Color color( int red, int green, int blue, int alpha ) { @@ -589,7 +589,7 @@ public class Constants { * Ermittelt das Vorzeichen der Zahl {@code x}. * * @param x Eine Zahl. - * @return -1, 1 oder 0. + * @return -1, 1 oder 0. */ public static final double sign( double x ) { return Math.signum(x); @@ -670,7 +670,7 @@ public class Constants { * Ermittelt den Sinus der Zahl {@code x}. * * @param x Eine Zahl. - * @return sin(x). + * @return {@code sin(x)}. */ public static final double sin( double x ) { return Math.sin(x); @@ -680,7 +680,7 @@ public class Constants { * Ermittelt den Kosinus der Zahl {@code x}. * * @param x Eine Zahl. - * @return cos(x). + * @return {@code cos(x)}. */ public static final double cos( double x ) { return Math.cos(x); @@ -690,7 +690,7 @@ public class Constants { * Ermittelt den Tangens der Zahl {@code x}. * * @param x Eine Zahl. - * @return tan(x). + * @return {@code tan(x)}. */ public static final double tan( double x ) { return Math.tan(x); @@ -700,7 +700,7 @@ public class Constants { * Ermittelt den Arkussinus der Zahl {@code x}. * * @param x Eine Zahl. - * @return asin(x). + * @return {@code asin(x)}. */ public static final double arcsin( double x ) { return Math.asin(x); @@ -710,7 +710,7 @@ public class Constants { * Ermittelt den Arkuskosinus der Zahl {@code x}. * * @param x Eine Zahl. - * @return acos(x). + * @return {@code acos(x)}. */ public static final double arccos( double x ) { return Math.acos(x); @@ -720,20 +720,20 @@ public class Constants { * Ermittelt den Arkusktangens der Zahl {@code x}. * * @param x Eine Zahl. - * @return atan(x). + * @return {@code atan(x)}. */ public static final double arctan( double x ) { return Math.atan(x); } /** - * Beschränkt die Zahl {@code x} auf das Intervall [min, max]. + * Beschränkt die Zahl {@code x} auf das Intervall {@code [min, max]}. * Liegt {@code x} außerhalb des Intervalls, wird eine der Grenzen * zurückgegeben. * * @param x Eine Zahl. * @param max Das Maximum des Intervalls. - * @return Eine Zahl im Intervall [min, max]. + * @return Eine Zahl im Intervall {@code [min, max]}. */ public static final double limit( double x, double min, double max ) { if( x > max ) { @@ -746,13 +746,13 @@ public class Constants { } /** - * Beschränkt die Zahl {@code x} auf das Intervall [min, max]. + * Beschränkt die Zahl {@code x} auf das Intervall {@code [min, max]}. * Liegt {@code x} außerhalb des Intervalls, wird eine der Grenzen * zurückgegeben. * * @param x Eine Zahl. * @param max Das Maximum des Intervalls. - * @return Eine Zahl im Intervall [min, max]. + * @return Eine Zahl im Intervall {@code [min, max]}. */ public static final int limit( int x, int min, int max ) { if( x > max ) { @@ -774,7 +774,7 @@ public class Constants { * * @param from Startwert * @param to Zielwert - * @param t Wert zwischen 0 und 1. + * @param t Wert zwischen 0 und 1. * @return Das Ergebnis der linearen Interpolation. */ public static final double interpolate( double from, double to, double t ) { @@ -885,8 +885,8 @@ public class Constants { * Erzeugt einen zufälligen Wahrheitswert. {@code true} wird mit der * Wahrscheinlichkeit {@code percent} Prozent erzeugt. * - * @param percent Eine Prozentzahl zwischen 0 und - * 100. + * @param percent Eine Prozentzahl zwischen 0 und + * 100. * @return Ein Wahrheitswert. */ public static final boolean randomBool( int percent ) { diff --git a/src/schule/ngb/zm/Drawable.java b/src/main/java/schule/ngb/zm/Drawable.java similarity index 92% rename from src/schule/ngb/zm/Drawable.java rename to src/main/java/schule/ngb/zm/Drawable.java index 3511f73..0b93f88 100644 --- a/src/schule/ngb/zm/Drawable.java +++ b/src/main/java/schule/ngb/zm/Drawable.java @@ -12,7 +12,7 @@ public interface Drawable { * Gibt an, ob das Objekt derzeit sichtbar ist (also gezeichnet werden * muss). * - * @return true, wenn das Objekt sichtbar ist. + * @return {@code true}, wenn das Objekt sichtbar ist. */ boolean isVisible(); diff --git a/src/schule/ngb/zm/DrawableLayer.java b/src/main/java/schule/ngb/zm/DrawableLayer.java similarity index 100% rename from src/schule/ngb/zm/DrawableLayer.java rename to src/main/java/schule/ngb/zm/DrawableLayer.java diff --git a/src/schule/ngb/zm/DrawingLayer.java b/src/main/java/schule/ngb/zm/DrawingLayer.java similarity index 100% rename from src/schule/ngb/zm/DrawingLayer.java rename to src/main/java/schule/ngb/zm/DrawingLayer.java diff --git a/src/schule/ngb/zm/GraphicsLayer.java b/src/main/java/schule/ngb/zm/GraphicsLayer.java similarity index 100% rename from src/schule/ngb/zm/GraphicsLayer.java rename to src/main/java/schule/ngb/zm/GraphicsLayer.java diff --git a/src/schule/ngb/zm/ImageLayer.java b/src/main/java/schule/ngb/zm/ImageLayer.java similarity index 100% rename from src/schule/ngb/zm/ImageLayer.java rename to src/main/java/schule/ngb/zm/ImageLayer.java diff --git a/src/schule/ngb/zm/Layer.java b/src/main/java/schule/ngb/zm/Layer.java similarity index 100% rename from src/schule/ngb/zm/Layer.java rename to src/main/java/schule/ngb/zm/Layer.java diff --git a/src/schule/ngb/zm/Options.java b/src/main/java/schule/ngb/zm/Options.java similarity index 100% rename from src/schule/ngb/zm/Options.java rename to src/main/java/schule/ngb/zm/Options.java diff --git a/src/schule/ngb/zm/Shape2DLayer.java b/src/main/java/schule/ngb/zm/Shape2DLayer.java similarity index 100% rename from src/schule/ngb/zm/Shape2DLayer.java rename to src/main/java/schule/ngb/zm/Shape2DLayer.java diff --git a/src/schule/ngb/zm/Spielemaschine.java b/src/main/java/schule/ngb/zm/Spielemaschine.java similarity index 100% rename from src/schule/ngb/zm/Spielemaschine.java rename to src/main/java/schule/ngb/zm/Spielemaschine.java diff --git a/src/schule/ngb/zm/Updatable.java b/src/main/java/schule/ngb/zm/Updatable.java similarity index 91% rename from src/schule/ngb/zm/Updatable.java rename to src/main/java/schule/ngb/zm/Updatable.java index 0a60447..0998e1c 100644 --- a/src/schule/ngb/zm/Updatable.java +++ b/src/main/java/schule/ngb/zm/Updatable.java @@ -9,7 +9,7 @@ public interface Updatable { /** * Gibt an, ob das Objekt gerade auf Aktualisierungen reagiert. - * @return true, wenn das Objekt aktiv ist. + * @return {@code true}, wenn das Objekt aktiv ist. */ public boolean isActive(); diff --git a/src/schule/ngb/zm/Vector.java b/src/main/java/schule/ngb/zm/Vector.java similarity index 100% rename from src/schule/ngb/zm/Vector.java rename to src/main/java/schule/ngb/zm/Vector.java diff --git a/src/schule/ngb/zm/Zeichenfenster.java b/src/main/java/schule/ngb/zm/Zeichenfenster.java similarity index 100% rename from src/schule/ngb/zm/Zeichenfenster.java rename to src/main/java/schule/ngb/zm/Zeichenfenster.java diff --git a/src/schule/ngb/zm/Zeichenleinwand.java b/src/main/java/schule/ngb/zm/Zeichenleinwand.java similarity index 95% rename from src/schule/ngb/zm/Zeichenleinwand.java rename to src/main/java/schule/ngb/zm/Zeichenleinwand.java index 73b9bae..232b688 100644 --- a/src/schule/ngb/zm/Zeichenleinwand.java +++ b/src/main/java/schule/ngb/zm/Zeichenleinwand.java @@ -90,7 +90,7 @@ public class Zeichenleinwand extends Canvas { * als letzte eingefügt. Die aufrufende Methode kann also nicht sicher sein, * dass die neue Ebene am Ende wirklich am Index {@code i} steht. * - * @param i Index der Ebene, beginnend mit 0. + * @param i Index der Ebene, beginnend mit 0. * @param layer Die neue Ebene. */ public void addLayer( int i, Layer layer ) { @@ -125,10 +125,10 @@ public class Zeichenleinwand extends Canvas { } /** - * Holt die Ebene am Index i (beginnend bei 0). + * Holt die Ebene am Index i (beginnend bei 0). * - * @param i Index der Ebene (beginnend bei 0). - * @return Die Ebene am Index i oder null. + * @param i Index der Ebene (beginnend bei 0). + * @return Die Ebene am Index i oder {@code null}. * @throws IndexOutOfBoundsException Falls der Index nicht existiert. */ public Layer getLayer( int i ) { @@ -141,7 +141,7 @@ public class Zeichenleinwand extends Canvas { /** * Sucht die erste Ebene des angegebenen Typs aus der Liste der Ebenen. - * Existiert keine solche Ebene, wird null zurückgegeben. + * Existiert keine solche Ebene, wird {@code null} zurückgegeben. * * @param clazz Typ der Ebene. * @param diff --git a/src/schule/ngb/zm/Zeichenmaschine.java b/src/main/java/schule/ngb/zm/Zeichenmaschine.java similarity index 99% rename from src/schule/ngb/zm/Zeichenmaschine.java rename to src/main/java/schule/ngb/zm/Zeichenmaschine.java index 93ed677..5f44473 100644 --- a/src/schule/ngb/zm/Zeichenmaschine.java +++ b/src/main/java/schule/ngb/zm/Zeichenmaschine.java @@ -531,6 +531,7 @@ public class Zeichenmaschine extends Constants { * vor {@code cleanup()} aufgerufen wird. */ private void cleanup() { + LOG.debug("%s shutting down.", APP_NAME); // Alle noch nicht ausgelösten Events werden entfernt eventQueue.clear(); // Alle noch nicht ausgeführten Tasks werden entfernt diff --git a/src/schule/ngb/zm/charts/BarChart.java b/src/main/java/schule/ngb/zm/charts/BarChart.java similarity index 100% rename from src/schule/ngb/zm/charts/BarChart.java rename to src/main/java/schule/ngb/zm/charts/BarChart.java diff --git a/src/schule/ngb/zm/charts/BasicChartValue.java b/src/main/java/schule/ngb/zm/charts/BasicChartValue.java similarity index 100% rename from src/schule/ngb/zm/charts/BasicChartValue.java rename to src/main/java/schule/ngb/zm/charts/BasicChartValue.java diff --git a/src/schule/ngb/zm/charts/ChartAxes.java b/src/main/java/schule/ngb/zm/charts/ChartAxes.java similarity index 100% rename from src/schule/ngb/zm/charts/ChartAxes.java rename to src/main/java/schule/ngb/zm/charts/ChartAxes.java diff --git a/src/schule/ngb/zm/charts/ChartValue.java b/src/main/java/schule/ngb/zm/charts/ChartValue.java similarity index 100% rename from src/schule/ngb/zm/charts/ChartValue.java rename to src/main/java/schule/ngb/zm/charts/ChartValue.java diff --git a/src/schule/ngb/zm/charts/LineChart.java b/src/main/java/schule/ngb/zm/charts/LineChart.java similarity index 100% rename from src/schule/ngb/zm/charts/LineChart.java rename to src/main/java/schule/ngb/zm/charts/LineChart.java diff --git a/src/schule/ngb/zm/charts/PieChart.java b/src/main/java/schule/ngb/zm/charts/PieChart.java similarity index 100% rename from src/schule/ngb/zm/charts/PieChart.java rename to src/main/java/schule/ngb/zm/charts/PieChart.java diff --git a/src/schule/ngb/zm/charts/RingChart.java b/src/main/java/schule/ngb/zm/charts/RingChart.java similarity index 100% rename from src/schule/ngb/zm/charts/RingChart.java rename to src/main/java/schule/ngb/zm/charts/RingChart.java diff --git a/src/schule/ngb/zm/media/Audio.java b/src/main/java/schule/ngb/zm/media/Audio.java similarity index 77% rename from src/schule/ngb/zm/media/Audio.java rename to src/main/java/schule/ngb/zm/media/Audio.java index e2f5137..fa64162 100644 --- a/src/schule/ngb/zm/media/Audio.java +++ b/src/main/java/schule/ngb/zm/media/Audio.java @@ -18,8 +18,8 @@ public interface Audio { * {@code isLooping() == true}, dann muss auch immer * {@code isPlaying() == true} gelten. * - * @return @return {@code true}, wenn das Medium in einer Schleife - * abgespielt wird, {@code false} sonst. + * @return {@code true}, wenn das Medium in einer Schleife abgespielt wird, + * {@code false} sonst. */ boolean isLooping(); @@ -36,17 +36,28 @@ public interface Audio { */ void setVolume( double volume ); + /** + * Gibt die aktuelle Lautstärkeeinstellung dieses Mediums zurück. + *

+ * Die Lautstärke wird auf einer linearen Skale angegeben, wobei 0 kein Ton + * und 1 volle Lautstärke bedeutet. Werte über 1 verstärken den Ton des + * Mediums. + * + * @return Die Lautstärke als linear skalierter Wert. + */ + double getVolume(); + /** * Startet die Wiedergabe des Mediums und beendet die Methode. Das * Audio-Medium wird einmal abgespielt und stoppt dann. */ - void playOnce(); + void play(); /** * Startet die Wiedergabe des Mediums und blockiert das Programm, bis die * Wiedergabe beendet ist. */ - void playOnceAndWait(); + void playAndWait(); /** * Spielt das Medium in einer kontinuierlichen Schleife ab. Die Methode diff --git a/src/schule/ngb/zm/media/Mixer.java b/src/main/java/schule/ngb/zm/media/Mixer.java similarity index 72% rename from src/schule/ngb/zm/media/Mixer.java rename to src/main/java/schule/ngb/zm/media/Mixer.java index 91b2064..f94ec4f 100644 --- a/src/schule/ngb/zm/media/Mixer.java +++ b/src/main/java/schule/ngb/zm/media/Mixer.java @@ -50,30 +50,53 @@ public class Mixer implements Audio { pAudio.setVolume(pVolumeFactor * volume); } + /** + * {@inheritDoc} + */ @Override public boolean isPlaying() { return audios.stream().anyMatch(aw -> aw.audio.isPlaying()); } + /** + * {@inheritDoc} + */ @Override public boolean isLooping() { return audios.stream().anyMatch(aw -> aw.audio.isLooping()); } + /** + * {@inheritDoc} + */ @Override public void setVolume( double pVolume ) { volume = (float) pVolume; audios.stream().forEach(aw -> aw.audio.setVolume(aw.volumeFactor * pVolume)); } + /** + * {@inheritDoc} + */ @Override - public void playOnce() { - audios.stream().forEach(aw -> aw.audio.playOnce()); + public double getVolume() { + return volume; } + /** + * {@inheritDoc} + */ @Override - public void playOnceAndWait() { - audios.stream().forEach(aw -> aw.audio.playOnce()); + public void play() { + audios.stream().forEach(aw -> aw.audio.play()); + } + + /** + * {@inheritDoc} + */ + @Override + public void playAndWait() { + audios.stream().forEach(aw -> aw.audio.play()); while( audios.stream().anyMatch(aw -> aw.audio.isPlaying()) ) { try { Thread.sleep(10); @@ -83,16 +106,25 @@ public class Mixer implements Audio { } } + /** + * {@inheritDoc} + */ @Override public void loop() { audios.stream().forEach(aw -> aw.audio.loop()); } + /** + * {@inheritDoc} + */ @Override public void stop() { audios.stream().forEach(aw -> aw.audio.stop()); } + /** + * {@inheritDoc} + */ @Override public void dispose() { if( isPlaying() ) { @@ -101,6 +133,18 @@ public class Mixer implements Audio { audios.stream().forEach(aw -> aw.audio.dispose()); } + /** + * Ändert die Lautstärke aller hinzugefügten Audiomedien in der angegebenen + * Zeit schrittweise, bis die angegebene Lautstärke erreicht ist. + *

+ * Zu beachten ist, dass die Lautstärke des Mixers angepasst wird. Das + * bedeutet, dass die Lautstärke der hinzugefügten Medien mit ihrem + * Lautstärkefaktor multipliziert werden. Die Medien haben am Ende also + * nicht unbedingt die Lautstärke {@code to}. + * + * @param to Der Zielwert für die Lautstärke. + * @param time Die Zeit, nach der die Änderung abgeschlossen sein soll. + */ public void fade( final double to, final int time ) { TaskRunner.run(new Runnable() { @Override @@ -108,9 +152,6 @@ public class Mixer implements Audio { final long start = System.currentTimeMillis(); double t = 0.0; double from = volume; - if( !isPlaying() ) { - playOnce(); - } do { setVolume(Constants.interpolate(from, to, t)); t = (double) (System.currentTimeMillis() - start) / (double) time; diff --git a/src/schule/ngb/zm/media/Music.java b/src/main/java/schule/ngb/zm/media/Music.java similarity index 56% rename from src/schule/ngb/zm/media/Music.java rename to src/main/java/schule/ngb/zm/media/Music.java index 1c53ba7..72ad34c 100644 --- a/src/schule/ngb/zm/media/Music.java +++ b/src/main/java/schule/ngb/zm/media/Music.java @@ -1,41 +1,82 @@ package schule.ngb.zm.media; import schule.ngb.zm.tasks.TaskRunner; +import schule.ngb.zm.util.Log; import schule.ngb.zm.util.ResourceStreamProvider; +import schule.ngb.zm.util.Validator; import javax.sound.sampled.*; import java.io.IOException; -import java.io.InputStream; -import java.util.logging.Level; -import java.util.logging.Logger; +import java.net.URL; +/** + * Ein Musikstück, dass im Projekt abgespielt werden soll. + *

+ * Im gegensatz zu einem {@link Sound} sind Musikstücke längere Audiodateien, + * die zum Beispiel als Hintergrundmusik ablaufen sollen. Die Musik wird daher + * nicht komplett in den Speicher geladen, sondern direkt aus der Audioquelle + * gestreamt und wiedergegeben. + */ public class Music implements Audio { // size of the byte buffer used to read/write the audio stream private static final int BUFFER_SIZE = 4096; + /** + * Ob der Sound gerade abgespielt wird. + */ private boolean playing = false; + /** + * Ob der Sound gerade in einer Schleife abgespielt wird. + */ private boolean looping = false; + /** + * Die Quelle des Musikstücks. + */ private String audioSource; + /** + * Der AudioStream, um die AUdiosdaten zulsen, falls dieser schon geöffnet + * wurde. Sonst {@code null}. + */ private AudioInputStream audioStream; + /** + * Die Line für die Ausgabe, falls diese schon geöffnet wurde. Sonst + * {@code null}. + */ private SourceDataLine audioLine; + /** + * Die Lautstärke der Musik. + */ private float volume = 0.8f; + /** + * Erstellt eine Musik aus der angegebenen Datei oder Webadresse. + * + * @param source Ein Dateipfad oder eine Webadresse. + * @throws NullPointerException Falls die Quelle {@code null} ist. + */ public Music( String source ) { + Validator.requireNotNull(source); this.audioSource = source; } + /** + * {@inheritDoc} + */ @Override public boolean isPlaying() { return playing; } + /** + * {@inheritDoc} + */ @Override public boolean isLooping() { if( !playing ) { @@ -44,6 +85,9 @@ public class Music implements Audio { return looping; } + /** + * {@inheritDoc} + */ @Override public void setVolume( double volume ) { this.volume = (float) volume; @@ -52,6 +96,18 @@ public class Music implements Audio { } } + /** + * {@inheritDoc} + */ + @Override + public double getVolume() { + return volume; + } + + /** + * Interne Methode, um die gesetzte Lautstärke vor dem Abspielen + * anzuwenden. + */ private void applyVolume() { FloatControl gainControl = (FloatControl) audioLine.getControl(FloatControl.Type.MASTER_GAIN); @@ -61,8 +117,11 @@ public class Music implements Audio { gainControl.setValue(vol); } + /** + * {@inheritDoc} + */ @Override - public void playOnce() { + public void play() { if( openLine() ) { TaskRunner.run(new Runnable() { @Override @@ -73,19 +132,28 @@ public class Music implements Audio { } } + /** + * {@inheritDoc} + */ @Override - public void playOnceAndWait() { + public void playAndWait() { if( openLine() ) { stream(); } } + /** + * {@inheritDoc} + */ @Override public void loop() { looping = true; - playOnce(); + play(); } + /** + * {@inheritDoc} + */ @Override public void stop() { playing = false; @@ -93,6 +161,9 @@ public class Music implements Audio { dispose(); } + /** + * {@inheritDoc} + */ @Override public void dispose() { if( audioLine != null ) { @@ -110,7 +181,8 @@ public class Music implements Audio { if( audioStream != null ) { audioStream.close(); } - } catch( IOException ex ) {} + } catch( IOException ex ) { + } audioLine = null; audioStream = null; @@ -124,15 +196,14 @@ public class Music implements Audio { int bytesRead = -1; try { - while (playing && (bytesRead = audioStream.read(bytesBuffer)) != -1) { + while( playing && (bytesRead = audioStream.read(bytesBuffer)) != -1 ) { audioLine.write(bytesBuffer, 0, bytesRead); } audioLine.drain(); audioLine.stop(); } catch( IOException ex ) { - LOGGER.warning("Error while playing Music source <" + audioSource + ">"); - LOGGER.throwing("Music", "stream", ex); + LOG.warn(ex, "Error while playing Music source <%s>", audioSource); } // Wait for the remaining audio to play @@ -154,14 +225,14 @@ public class Music implements Audio { } try { - InputStream in = ResourceStreamProvider.getResourceStream(audioSource); - if( in != null ) { - final AudioInputStream inStream = AudioSystem.getAudioInputStream(in); + URL url = ResourceStreamProvider.getResourceURL(audioSource); + if( url != null ) { + final AudioInputStream inStream = AudioSystem.getAudioInputStream(url); AudioFormat format = inStream.getFormat(); final int ch = format.getChannels(); final float rate = format.getSampleRate(); - AudioFormat outFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, rate, 16, ch, ch*2, rate, false); + AudioFormat outFormat = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, rate, 16, ch, ch * 2, rate, false); DataLine.Info info = new DataLine.Info(SourceDataLine.class, outFormat); @@ -172,28 +243,33 @@ public class Music implements Audio { audioStream = AudioSystem.getAudioInputStream(outFormat, inStream); return true; } else { - LOGGER.warning("Sound source <" + audioSource + "> could not be played: No audio source found."); + LOG.warn("Sound source <%s> could not be played: No audio source found.", audioSource); } } catch( UnsupportedAudioFileException ex ) { - LOGGER.log(Level.WARNING, "Sound source <" + audioSource + "> could not be played: The specified audio file is not supported.", ex); + LOG.warn(ex, "Sound source <%s> could not be played: The specified audio file is not supported.", audioSource); } catch( LineUnavailableException ex ) { - LOGGER.log(Level.WARNING, "Sound source <" + audioSource + "> could not be played: Audio line for playing back is unavailable.", ex); + LOG.warn(ex, "Sound source <%s> could not be played: Audio line for playing back is unavailable.", audioSource); } catch( IOException ex ) { - LOGGER.log(Level.WARNING, "Sound source <" + audioSource + "> could not be played: Error playing the audio file.", ex); + LOG.warn(ex, "Sound source <%s> could not be played: Error playing the audio file.", audioSource); } return false; } private void streamingStopped() { - playing = false; dispose(); if( looping ) { - playOnce(); + if( openLine() ) { + stream(); + } else { + playing = false; + looping = false; + } + } else { + playing = false; } } - //private static final Logger LOGGER = Logger.getLogger("schule.ngb.zm.media.Music"); - private static final Logger LOGGER = Logger.getLogger(Music.class.getName()); + private static final Log LOG = Log.getLogger(Music.class); } diff --git a/src/main/java/schule/ngb/zm/media/Sound.java b/src/main/java/schule/ngb/zm/media/Sound.java new file mode 100644 index 0000000..ece650d --- /dev/null +++ b/src/main/java/schule/ngb/zm/media/Sound.java @@ -0,0 +1,309 @@ +package schule.ngb.zm.media; + +import schule.ngb.zm.util.Log; +import schule.ngb.zm.util.ResourceStreamProvider; +import schule.ngb.zm.util.Validator; + +import javax.sound.sampled.*; +import java.io.IOException; +import java.io.InputStream; +import java.util.logging.Logger; + +/** + * Wiedergabe kurzer Soundclips, die mehrmals wiederverwendet werden. + *

+ * In Spielen und anderen Projekten gibt es oftmals eine Reihe kurzer Sounds, + * die zusammen mit bestimmten Aktionen wiedergegeben werden (zum Beispiel, wenn + * die Spielfigur springt, wenn zwei Objekte kollidieren, usw.). Sounds werden + * komplett in den Speicher geladen und können dadurch immer wieder, als + * Schleife oder auch nur Abschnittsweise abgespielt werden. + *

+ * Für längre Musikstücke (beispielsweise Hintergrundmusik) bietet sich eher die + * KLasse {@link Music} an. + */ +@SuppressWarnings( "unused" ) +public class Sound implements Audio { + + /** + * Ob der Sound gerade abgespielt wird. + */ + private boolean playing = false; + + /** + * Ob der Sound gerade in einer Schleife abgespielt wird. + */ + private boolean looping = false; + + /** + * Die Quelle des Musikstücks. + */ + private String audioSource; + + /** + * Der Clip, falls er schon geladen wurde, sonst {@code null}. + */ + private Clip audioClip; + + /** + * Ob die Resourcen des Clips im Speicher nach dem nächsten Abspielen + * freigegeben werden sollen. + */ + private boolean disposeAfterPlay = false; + + /** + * Die Lautstärke des Clips. + */ + private float volume = 0.8f; + + /** + * Erstellt einen Sound aus der angegebene Quelle. + * + * @param source Ein Dateipfad oder eine Webadresse. + * @throws NullPointerException Falls die Quelle {@code null} ist. + */ + public Sound( String source ) { + Validator.requireNotNull(source); + this.audioSource = source; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isPlaying() { + // return audioClip != null && audioClip.isRunning(); + return playing; + } + + /** + * {@inheritDoc} + */ + @Override + public boolean isLooping() { + if( !playing ) { + looping = false; + } + return looping; + } + + /** + * {@inheritDoc} + */ + @Override + public void setVolume( double volume ) { + this.volume = (float) volume; + if( audioClip != null ) { + applyVolume(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public double getVolume() { + return volume; + } + + /** + * Interne Methode, um die gesetzte Lautstärke vor dem Abspielen + * anzuwenden. + */ + private void applyVolume() { + FloatControl gainControl = + (FloatControl) audioClip.getControl(FloatControl.Type.MASTER_GAIN); + + float vol = 20f * (float) Math.log10(volume); + // vol = (float) Constants.limit(vol, gainControl.getMinimum(), gainControl.getMaximum()); + gainControl.setValue(vol); + } + + /** + * {@inheritDoc} + */ + @Override + public void stop() { + looping = false; + if( audioClip.isRunning() ) { + audioClip.stop(); + } + playing = false; + } + + /** + * {@inheritDoc} + */ + @Override + public void play() { + if( this.openClip() ) { + audioClip.start(); + playing = true; + } + } + + /** + * {@inheritDoc} + */ + @Override + public void playAndWait() { + this.play(); + + long audioLen = audioClip.getMicrosecondLength(); + while( playing ) { + try { + long ms = (audioLen - audioClip.getMicrosecondPosition()) / 1000L; + Thread.sleep(ms); + } catch( InterruptedException ex ) { + // Ignore + } + } + + audioClip.close(); + } + + /** + * Spielt den Sound genau einmal ab und gibt danach alle Resourcen des Clips + * frei. + *

+ * Der Aufruf ist effektiv gleich zu + *


+	 * clip.playAndWait();
+	 * clip.dispose();
+	 * 
+ * allerdings wird der aufrufende Thread nicht blockiert und + * {@link #dispose()} automatisch am Ende aufgerufen. + */ + public void playOnce() { + disposeAfterPlay = true; + play(); + } + + /** + * Spielt den Sound genau einmal ab und gibt danach alle Resourcen des Clips + * frei. + *

+ * Der Aufruf entspricht + *


+	 * clip.playAndWait();
+	 * clip.dispose();
+	 * 
+ */ + public void playOnceAndWait() { + disposeAfterPlay = true; + playAndWait(); + } + + /** + * {@inheritDoc} + */ + @Override + public void loop() { + loop(Clip.LOOP_CONTINUOUSLY); + } + + /** + * Wiederholt den Sound die angegebene Anzahl an Wiederholungen ab und stoppt + * die Wiedergabe dann. + * @param count Anzahl der Wiederholungen. + */ + public void loop( int count ) { + if( count > 0 ) { + int loopCount = count; + if( loopCount != Clip.LOOP_CONTINUOUSLY ) { + if( loopCount <= 0 ) { + return; + } + // Adjust Number of loops + loopCount -= 1; + } + if( openClip() ) { + looping = true; + audioClip.loop(loopCount); + playing = true; + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public void dispose() { + if( audioClip != null ) { + if( audioClip.isRunning() ) { + audioClip.stop(); + } + audioClip.close(); + audioClip = null; + } + } + + private boolean openClip() { + if( audioClip != null ) { + audioClip.setFramePosition(0); + return true; + } + + try { + InputStream in = ResourceStreamProvider.getResourceStream(audioSource); + if( in != null ) { + AudioInputStream audioStream = AudioSystem.getAudioInputStream(in); + AudioFormat format = audioStream.getFormat(); + DataLine.Info info = new DataLine.Info(Clip.class, format); + + audioClip = (Clip) AudioSystem.getLine(info); + audioClip.addLineListener(new LineListener() { + @Override + public void update( LineEvent event ) { + if( event.getType() == LineEvent.Type.STOP ) { + playbackStopped(); + } + } + }); + audioClip.open(audioStream); + applyVolume(); + return true; + } else { + LOG.warn("Sound source <%s> could not be played: No audio source found.", audioSource); + } + } catch( UnsupportedAudioFileException ex ) { + LOG.warn(ex, "Sound source <%s> could not be played: The specified audio file is not supported.", audioSource); + } catch( LineUnavailableException ex ) { + LOG.warn(ex, "Sound source <%s> could not be played: Audio line for playing back is unavailable.", audioSource); + } catch( IOException ex ) { + LOG.warn(ex, "Sound source <%s> could not be played: Error playing the audio file.", audioSource); + } + return false; + } + + /*@Override + public void update( LineEvent event ) { + LineEvent.Type type = event.getType(); + + if( type == LineEvent.Type.START ) { + playing = true; + } else if( type == LineEvent.Type.STOP ) { + playing = false; + if( disposeAfterPlay ) { + this.dispose(); + disposeAfterPlay = false; + } + } + }*/ + + /** + * Interne Methode, die aufgerufen wird, wenn die Wiedergabe gestoppt wird. + * Entweder durch einen Aufruf von {@link #stop()} oder, weil die Wiedergabe + * nach {@link #playOnce()} beendet wurde. + */ + private void playbackStopped() { + playing = false; + if( disposeAfterPlay ) { + this.dispose(); + disposeAfterPlay = false; + } + } + + private static final Log LOG = Log.getLogger(Sound.class); + +} diff --git a/src/schule/ngb/zm/shapes/Arc.java b/src/main/java/schule/ngb/zm/shapes/Arc.java similarity index 100% rename from src/schule/ngb/zm/shapes/Arc.java rename to src/main/java/schule/ngb/zm/shapes/Arc.java diff --git a/src/schule/ngb/zm/shapes/Arrow.java b/src/main/java/schule/ngb/zm/shapes/Arrow.java similarity index 100% rename from src/schule/ngb/zm/shapes/Arrow.java rename to src/main/java/schule/ngb/zm/shapes/Arrow.java diff --git a/src/schule/ngb/zm/shapes/Bounds.java b/src/main/java/schule/ngb/zm/shapes/Bounds.java similarity index 100% rename from src/schule/ngb/zm/shapes/Bounds.java rename to src/main/java/schule/ngb/zm/shapes/Bounds.java diff --git a/src/schule/ngb/zm/shapes/Circle.java b/src/main/java/schule/ngb/zm/shapes/Circle.java similarity index 100% rename from src/schule/ngb/zm/shapes/Circle.java rename to src/main/java/schule/ngb/zm/shapes/Circle.java diff --git a/src/schule/ngb/zm/shapes/Curve.java b/src/main/java/schule/ngb/zm/shapes/Curve.java similarity index 100% rename from src/schule/ngb/zm/shapes/Curve.java rename to src/main/java/schule/ngb/zm/shapes/Curve.java diff --git a/src/schule/ngb/zm/shapes/CustomShape.java b/src/main/java/schule/ngb/zm/shapes/CustomShape.java similarity index 100% rename from src/schule/ngb/zm/shapes/CustomShape.java rename to src/main/java/schule/ngb/zm/shapes/CustomShape.java diff --git a/src/schule/ngb/zm/shapes/Ellipse.java b/src/main/java/schule/ngb/zm/shapes/Ellipse.java similarity index 100% rename from src/schule/ngb/zm/shapes/Ellipse.java rename to src/main/java/schule/ngb/zm/shapes/Ellipse.java diff --git a/src/schule/ngb/zm/shapes/FilledShape.java b/src/main/java/schule/ngb/zm/shapes/FilledShape.java similarity index 100% rename from src/schule/ngb/zm/shapes/FilledShape.java rename to src/main/java/schule/ngb/zm/shapes/FilledShape.java diff --git a/src/schule/ngb/zm/shapes/Kite.java b/src/main/java/schule/ngb/zm/shapes/Kite.java similarity index 100% rename from src/schule/ngb/zm/shapes/Kite.java rename to src/main/java/schule/ngb/zm/shapes/Kite.java diff --git a/src/schule/ngb/zm/shapes/Line.java b/src/main/java/schule/ngb/zm/shapes/Line.java similarity index 100% rename from src/schule/ngb/zm/shapes/Line.java rename to src/main/java/schule/ngb/zm/shapes/Line.java diff --git a/src/schule/ngb/zm/shapes/Picture.java b/src/main/java/schule/ngb/zm/shapes/Picture.java similarity index 100% rename from src/schule/ngb/zm/shapes/Picture.java rename to src/main/java/schule/ngb/zm/shapes/Picture.java diff --git a/src/schule/ngb/zm/shapes/Point.java b/src/main/java/schule/ngb/zm/shapes/Point.java similarity index 100% rename from src/schule/ngb/zm/shapes/Point.java rename to src/main/java/schule/ngb/zm/shapes/Point.java diff --git a/src/schule/ngb/zm/shapes/Polygon.java b/src/main/java/schule/ngb/zm/shapes/Polygon.java similarity index 100% rename from src/schule/ngb/zm/shapes/Polygon.java rename to src/main/java/schule/ngb/zm/shapes/Polygon.java diff --git a/src/schule/ngb/zm/shapes/Quad.java b/src/main/java/schule/ngb/zm/shapes/Quad.java similarity index 100% rename from src/schule/ngb/zm/shapes/Quad.java rename to src/main/java/schule/ngb/zm/shapes/Quad.java diff --git a/src/schule/ngb/zm/shapes/Rectangle.java b/src/main/java/schule/ngb/zm/shapes/Rectangle.java similarity index 100% rename from src/schule/ngb/zm/shapes/Rectangle.java rename to src/main/java/schule/ngb/zm/shapes/Rectangle.java diff --git a/src/schule/ngb/zm/shapes/Rhombus.java b/src/main/java/schule/ngb/zm/shapes/Rhombus.java similarity index 100% rename from src/schule/ngb/zm/shapes/Rhombus.java rename to src/main/java/schule/ngb/zm/shapes/Rhombus.java diff --git a/src/schule/ngb/zm/shapes/RoundedRectangle.java b/src/main/java/schule/ngb/zm/shapes/RoundedRectangle.java similarity index 100% rename from src/schule/ngb/zm/shapes/RoundedRectangle.java rename to src/main/java/schule/ngb/zm/shapes/RoundedRectangle.java diff --git a/src/schule/ngb/zm/shapes/Shape.java b/src/main/java/schule/ngb/zm/shapes/Shape.java similarity index 99% rename from src/schule/ngb/zm/shapes/Shape.java rename to src/main/java/schule/ngb/zm/shapes/Shape.java index 7d3d3cc..6e3866b 100644 --- a/src/schule/ngb/zm/shapes/Shape.java +++ b/src/main/java/schule/ngb/zm/shapes/Shape.java @@ -169,7 +169,7 @@ public abstract class Shape extends FilledShape { * Unterklassen sollten diese Methode überschreiben, um weitere * Eigenschaften zu kopieren (zum Beispiel den Radius eines Kreises). Mit * dem Aufruf - * super.copyFrom(shape) sollten die Basiseigenschaften + * {@code super.copyFrom(shape)} sollten die Basiseigenschaften * kopiert werden. * * @param shape @@ -222,7 +222,7 @@ public abstract class Shape extends FilledShape { * {@code buff} nach oben verschoben. * * @param shape - * @param anchor + * @param dir * @param buff */ public void moveTo( Shape shape, Options.Direction dir, double buff ) { diff --git a/src/schule/ngb/zm/shapes/ShapeGroup.java b/src/main/java/schule/ngb/zm/shapes/ShapeGroup.java similarity index 100% rename from src/schule/ngb/zm/shapes/ShapeGroup.java rename to src/main/java/schule/ngb/zm/shapes/ShapeGroup.java diff --git a/src/schule/ngb/zm/shapes/ShapesLayer.java b/src/main/java/schule/ngb/zm/shapes/ShapesLayer.java similarity index 100% rename from src/schule/ngb/zm/shapes/ShapesLayer.java rename to src/main/java/schule/ngb/zm/shapes/ShapesLayer.java diff --git a/src/schule/ngb/zm/shapes/StrokedShape.java b/src/main/java/schule/ngb/zm/shapes/StrokedShape.java similarity index 100% rename from src/schule/ngb/zm/shapes/StrokedShape.java rename to src/main/java/schule/ngb/zm/shapes/StrokedShape.java diff --git a/src/schule/ngb/zm/shapes/Text.java b/src/main/java/schule/ngb/zm/shapes/Text.java similarity index 100% rename from src/schule/ngb/zm/shapes/Text.java rename to src/main/java/schule/ngb/zm/shapes/Text.java diff --git a/src/schule/ngb/zm/shapes/Triangle.java b/src/main/java/schule/ngb/zm/shapes/Triangle.java similarity index 100% rename from src/schule/ngb/zm/shapes/Triangle.java rename to src/main/java/schule/ngb/zm/shapes/Triangle.java diff --git a/src/schule/ngb/zm/tasks/DelayedTask.java b/src/main/java/schule/ngb/zm/tasks/DelayedTask.java similarity index 100% rename from src/schule/ngb/zm/tasks/DelayedTask.java rename to src/main/java/schule/ngb/zm/tasks/DelayedTask.java diff --git a/src/schule/ngb/zm/tasks/FrameSynchronizedTask.java b/src/main/java/schule/ngb/zm/tasks/FrameSynchronizedTask.java similarity index 100% rename from src/schule/ngb/zm/tasks/FrameSynchronizedTask.java rename to src/main/java/schule/ngb/zm/tasks/FrameSynchronizedTask.java diff --git a/src/schule/ngb/zm/tasks/FramerateLimitedTask.java b/src/main/java/schule/ngb/zm/tasks/FramerateLimitedTask.java similarity index 100% rename from src/schule/ngb/zm/tasks/FramerateLimitedTask.java rename to src/main/java/schule/ngb/zm/tasks/FramerateLimitedTask.java diff --git a/src/schule/ngb/zm/tasks/RateLimitedTask.java b/src/main/java/schule/ngb/zm/tasks/RateLimitedTask.java similarity index 100% rename from src/schule/ngb/zm/tasks/RateLimitedTask.java rename to src/main/java/schule/ngb/zm/tasks/RateLimitedTask.java diff --git a/src/schule/ngb/zm/tasks/Task.java b/src/main/java/schule/ngb/zm/tasks/Task.java similarity index 100% rename from src/schule/ngb/zm/tasks/Task.java rename to src/main/java/schule/ngb/zm/tasks/Task.java diff --git a/src/schule/ngb/zm/tasks/TaskRunner.java b/src/main/java/schule/ngb/zm/tasks/TaskRunner.java similarity index 100% rename from src/schule/ngb/zm/tasks/TaskRunner.java rename to src/main/java/schule/ngb/zm/tasks/TaskRunner.java diff --git a/src/schule/ngb/zm/turtle/TurtleLayer.java b/src/main/java/schule/ngb/zm/turtle/TurtleLayer.java similarity index 100% rename from src/schule/ngb/zm/turtle/TurtleLayer.java rename to src/main/java/schule/ngb/zm/turtle/TurtleLayer.java diff --git a/src/schule/ngb/zm/util/FontLoader.java b/src/main/java/schule/ngb/zm/util/FontLoader.java similarity index 100% rename from src/schule/ngb/zm/util/FontLoader.java rename to src/main/java/schule/ngb/zm/util/FontLoader.java diff --git a/src/schule/ngb/zm/util/ImageLoader.java b/src/main/java/schule/ngb/zm/util/ImageLoader.java similarity index 99% rename from src/schule/ngb/zm/util/ImageLoader.java rename to src/main/java/schule/ngb/zm/util/ImageLoader.java index 3bddbfb..4a7c5c9 100644 --- a/src/schule/ngb/zm/util/ImageLoader.java +++ b/src/main/java/schule/ngb/zm/util/ImageLoader.java @@ -47,7 +47,7 @@ public class ImageLoader { /** * Lädt ein Bild von der angegebenen Quelle source und gibt das - * Bild zurück oder null, wenn das Bild nicht geladen werden + * Bild zurück oder {@code null}, wenn das Bild nicht geladen werden * konnte. Ist ein Bild mit der angegebenen Quelle im Cache, wird das * gespeicherte Bild zurückgegeben. Dies kann mit {@code caching = false} * verhindert werden. diff --git a/src/schule/ngb/zm/util/Log.java b/src/main/java/schule/ngb/zm/util/Log.java similarity index 79% rename from src/schule/ngb/zm/util/Log.java rename to src/main/java/schule/ngb/zm/util/Log.java index dd22f72..e7cac7f 100644 --- a/src/schule/ngb/zm/util/Log.java +++ b/src/main/java/schule/ngb/zm/util/Log.java @@ -1,5 +1,11 @@ package schule.ngb.zm.util; +import java.io.IOException; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.Enumeration; import java.util.Iterator; import java.util.function.Supplier; @@ -30,6 +36,10 @@ public final class Log { private static final String ROOT_LOGGER = "schule.ngb.zm"; + private static final String DEFAULT_LOG_FORMAT = "[%1$tT] [%4$11s] %5$s %6$s%n"; + + private static final String DEFAULT_DEBUG_FORMAT = "[%1$tT] [%4$11s] (%2$s) %5$s %6$s%n"; + private static boolean LOGGING_INIT = false; /** @@ -43,7 +53,7 @@ public final class Log { * * @see #enableGlobalLevel(Level) */ - public static final void enableGlobalDebugging() { + public static void enableGlobalDebugging() { enableGlobalLevel(ALL); } @@ -68,32 +78,18 @@ public final class Log { * @param level Das Level, auf das alle {@code Logger} und {@code Handler} * mindestens herabgesenkt werden sollen. */ - public static final void xenableGlobalLevel( Level level ) { + public static void enableGlobalLevel( Level level ) { int lvl = Validator.requireNotNull(level).intValue(); + ensureRootLoggerIntialized(); - Logger rootLogger = Logger.getLogger(ROOT_LOGGER); - rootLogger.setLevel(level); - - for( Handler handler : rootLogger.getHandlers() ) { - if( handler instanceof ConsoleHandler ) { - Level handlerLevel = handler.getLevel(); - if( handlerLevel == null || handler.getLevel().intValue() > lvl ) { - handler.setLevel(level); - } - } - } - } - - public static final void enableGlobalLevel( Level level ) { - int lvl = Validator.requireNotNull(level).intValue(); - - // Decrease level of root level ConsoleHandlers for outpu + // Decrease level of root level ConsoleHandlers for output Logger rootLogger = Logger.getLogger(""); for( Handler handler : rootLogger.getHandlers() ) { if( handler instanceof ConsoleHandler ) { Level handlerLevel = handler.getLevel(); if( handlerLevel == null || handler.getLevel().intValue() > lvl ) { handler.setLevel(level); + handler.setFormatter(new LogFormatter()); } } } @@ -117,16 +113,42 @@ public final class Log { } } } + + Logger LOG = Logger.getLogger(ROOT_LOGGER); + LOG.fine("Debug logging enabled."); } - public static final Log getLogger( Class clazz ) { - if( !LOGGING_INIT ) { - Logger.getLogger(ROOT_LOGGER); - LOGGING_INIT = true; - } + public static Log getLogger( Class clazz ) { + ensureRootLoggerIntialized(); return new Log(clazz); } + private static void ensureRootLoggerIntialized() { + if( LOGGING_INIT ) { + return; + } + + Logger rootLogger = Logger.getLogger(ROOT_LOGGER); + rootLogger.setLevel(Level.INFO); + + if( System.getProperty("java.util.logging.SimpleFormatter.format") == null + && LogManager.getLogManager().getProperty("java.util.logging.SimpleFormatter.format") == null ) { + System.setProperty("java.util.logging.SimpleFormatter.format", DEFAULT_LOG_FORMAT); + rootLogger.addHandler(new StreamHandler(System.err, new LogFormatter())); + rootLogger.setUseParentHandlers(false); + } + if( rootLogger.getUseParentHandlers() ) { + // This logger was not configured somewhere else + // Add a Handler and Formatter + + //StreamHandler rootHandler = new StreamHandler(System.out, new SimpleFormatter()); + //rootLogger.addHandler(rootHandler); + //rootLogger.setUseParentHandlers(false); + } + + LOGGING_INIT = true; + } + private final Logger LOGGER; private final Class sourceClass; @@ -315,4 +337,40 @@ public final class Log { this.log(FINER, throwable, msgSupplier); } + static final class LogFormatter extends Formatter { + + @Override + public String format( LogRecord record ) { + ZonedDateTime zdt = ZonedDateTime.ofInstant( + record.getInstant(), ZoneId.systemDefault()); + String source; + if (record.getSourceClassName() != null) { + source = record.getSourceClassName(); + if (record.getSourceMethodName() != null) { + source += " " + record.getSourceMethodName(); + } + } else { + source = record.getLoggerName(); + } + String message = formatMessage(record); + String throwable = ""; + if (record.getThrown() != null) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + pw.println(); + record.getThrown().printStackTrace(pw); + pw.close(); + throwable = sw.toString(); + } + return String.format(DEFAULT_LOG_FORMAT, + zdt, + source, + record.getLoggerName(), + record.getLevel().getLocalizedName(), + message, + throwable); + } + + } + } diff --git a/src/schule/ngb/zm/util/ResourceStreamProvider.java b/src/main/java/schule/ngb/zm/util/ResourceStreamProvider.java similarity index 100% rename from src/schule/ngb/zm/util/ResourceStreamProvider.java rename to src/main/java/schule/ngb/zm/util/ResourceStreamProvider.java diff --git a/src/schule/ngb/zm/util/Validator.java b/src/main/java/schule/ngb/zm/util/Validator.java similarity index 100% rename from src/schule/ngb/zm/util/Validator.java rename to src/main/java/schule/ngb/zm/util/Validator.java diff --git a/res/Icon.afdesign b/src/main/resources/Icon.afdesign similarity index 100% rename from res/Icon.afdesign rename to src/main/resources/Icon.afdesign diff --git a/res/icon_128.png b/src/main/resources/icon_128.png similarity index 100% rename from res/icon_128.png rename to src/main/resources/icon_128.png diff --git a/res/icon_32.png b/src/main/resources/icon_32.png similarity index 100% rename from res/icon_32.png rename to src/main/resources/icon_32.png diff --git a/res/icon_512.png b/src/main/resources/icon_512.png similarity index 100% rename from res/icon_512.png rename to src/main/resources/icon_512.png diff --git a/res/icon_64.png b/src/main/resources/icon_64.png similarity index 100% rename from res/icon_64.png rename to src/main/resources/icon_64.png diff --git a/src/schule/ngb/zm/media/Sound.java b/src/schule/ngb/zm/media/Sound.java deleted file mode 100644 index ceda917..0000000 --- a/src/schule/ngb/zm/media/Sound.java +++ /dev/null @@ -1,204 +0,0 @@ -package schule.ngb.zm.media; - -import schule.ngb.zm.util.ResourceStreamProvider; - -import javax.sound.sampled.*; -import java.io.IOException; -import java.io.InputStream; -import java.util.logging.Logger; - -public class Sound implements Audio { - - private boolean playing = false; - - private boolean looping = false; - - private String audioSource; - - private Clip audioClip; - - private boolean disposeAfterPlay = false; - - private float volume = 0.8f; - - public Sound( String source ) { - this.audioSource = source; - } - - public boolean isPlaying() { - // return audioClip != null && audioClip.isRunning(); - return playing; - } - - public boolean isLooping() { - if( !playing ) { - looping = false; - } - return looping; - } - - public void setVolume( double volume ) { - this.volume = (float) volume; - if( audioClip != null ) { - applyVolume(); - } - } - - private void applyVolume() { - FloatControl gainControl = - (FloatControl) audioClip.getControl(FloatControl.Type.MASTER_GAIN); - - float vol = 20f * (float) Math.log10(volume); - // vol = (float) Constants.limit(vol, gainControl.getMinimum(), gainControl.getMaximum()); - gainControl.setValue(vol); - } - - public void stop() { - looping = false; - if( audioClip.isRunning() ) { - audioClip.stop(); - } - playing = false; - } - - public void play() { - if( this.openClip() ) { - audioClip.start(); - playing = true; - } - } - - public void playOnce() { - disposeAfterPlay = true; - play(); - } - - public void playOnceAndWait() { - disposeAfterPlay = true; - playAndWait(); - } - - public void playAndWait() { - this.play(); - - long audioLen = audioClip.getMicrosecondLength(); - while( playing ) { - try { - long ms = (audioLen - audioClip.getMicrosecondPosition()) / 1000L; - Thread.sleep(ms); - } catch( InterruptedException ex ) { - // Ignore - } - } - - audioClip.close(); - } - - public void loop() { - loop(Clip.LOOP_CONTINUOUSLY); - } - - public void loop( int count ) { - int loopCount = count; - if( loopCount != Clip.LOOP_CONTINUOUSLY ) { - if( loopCount <= 0 ) { - return; - } - // Adjust Number of loops - loopCount -= 1; - } - if( openClip() ) { - looping = true; - audioClip.loop(loopCount); - playing = true; - } - } - - public void dispose() { - if( audioClip != null ) { - if( audioClip.isRunning() ) { - audioClip.stop(); - } - audioClip.close(); - audioClip = null; - } - } - - private boolean openClip() { - if( audioClip != null ) { - audioClip.setFramePosition(0); - return true; - } - - try { - InputStream in = ResourceStreamProvider.getResourceStream(audioSource); - if( in != null ) { - AudioInputStream audioStream = AudioSystem.getAudioInputStream(in); - AudioFormat format = audioStream.getFormat(); - DataLine.Info info = new DataLine.Info(Clip.class, format); - - audioClip = (Clip) AudioSystem.getLine(info); - audioClip.addLineListener(new LineListener() { - @Override - public void update( LineEvent event ) { - if( event.getType() == LineEvent.Type.STOP ) { - playbackStopped(); - } - } - }); - audioClip.open(audioStream); - applyVolume(); - return true; - } else { - LOGGER.warning("Sound source " + audioSource + " could not be played: No audio source found."); - } - } catch( UnsupportedAudioFileException ex ) { - LOGGER.warning("Sound source " + audioSource + " could not be played: The specified audio file is not supported."); - LOGGER.throwing("Sound", "openClip", ex); - } catch( LineUnavailableException ex ) { - LOGGER.warning("Sound source " + audioSource + " could not be played: Audio line for playing back is unavailable."); - LOGGER.throwing("Sound", "openClip", ex); - } catch( IOException ex ) { - LOGGER.warning("Sound source " + audioSource + " could not be played: Error playing the audio file."); - LOGGER.throwing("Sound", "openClip", ex); - } - return false; - } - - /*@Override - public void update( LineEvent event ) { - LineEvent.Type type = event.getType(); - - if( type == LineEvent.Type.START ) { - playing = true; - } else if( type == LineEvent.Type.STOP ) { - playing = false; - if( disposeAfterPlay ) { - this.dispose(); - disposeAfterPlay = false; - } - } - }*/ - - private void playbackStopped() { - playing = false; - if( disposeAfterPlay ) { - this.dispose(); - disposeAfterPlay = false; - } - } - - /* - public void addLineListener( LineListener listener ) { - if( audioClip == null ) { - openClip(); - } - if( audioClip != null ) { - audioClip.addLineListener(listener); - } - } - */ - - private static final Logger LOGGER = Logger.getLogger(Sound.class.getName()); - -} diff --git a/test/src/schule/ngb/zm/TestColor.java b/src/test/java/schule/ngb/zm/ColorTest.java similarity index 51% rename from test/src/schule/ngb/zm/TestColor.java rename to src/test/java/schule/ngb/zm/ColorTest.java index a27ca89..58f2ec3 100644 --- a/test/src/schule/ngb/zm/TestColor.java +++ b/src/test/java/schule/ngb/zm/ColorTest.java @@ -1,13 +1,13 @@ package schule.ngb.zm; -import org.junit.Test; +import org.junit.jupiter.api.Test; -import static org.junit.Assert.*; +import static org.junit.jupiter.api.Assertions.*; -public class TestColor { +class ColorTest { @Test - public void colors() { + public void init() { Color c; c = new Color(); @@ -39,7 +39,7 @@ public class TestColor { } @Test - public void parseColors() { + public void parse() { Color c; c = Color.getRGBColor(0x00FF00FF); @@ -86,7 +86,74 @@ public class TestColor { } @Test - public void hsl() { + void testEquals() { + Color c1 = new Color(254, 98, 12); + Color c2 = new Color(254, 98, 12); + assertNotSame(c1, c2); + assertEquals(c1, c2); + assertEquals(c1, c1); + c2 = new Color(c1); + assertNotSame(c1, c2); + assertEquals(c1, c2); + + Color yellow = new Color(255, 255, 0); + assertEquals(java.awt.Color.YELLOW, yellow); + assertNotEquals(java.awt.Color.YELLOW, Color.YELLOW); + } + + @Test + void construct() { + Color c; + // Empty color is white + c = new Color(); + assertEquals(Color.BLACK, c); + // One arg is shade of gray + c = new Color(255); + assertEquals(Color.WHITE, c); + c = new Color(0); + assertEquals(Color.BLACK, c); + c = new Color(64); + assertEquals(Color.DARKGRAY, c); + c = new Color(192); + assertEquals(Color.LIGHTGRAY, c); + // RGB colors + c = new Color(0,0,0); + assertEquals(Color.BLACK, c); + c = new Color(255,0,0); + assertEquals(java.awt.Color.RED, c.getJavaColor()); + c = new Color(0,255,0); + assertEquals(java.awt.Color.GREEN, c.getJavaColor()); + c = new Color(0,0,255); + assertEquals(java.awt.Color.BLUE, c.getJavaColor()); + // From java.awt.Color + c = new Color(java.awt.Color.YELLOW); + assertEquals(java.awt.Color.YELLOW, c.getJavaColor()); + } + + @Test + void getRGBColor() { + Color c1 = Color.getRGBColor(0xFFFF0000); + assertEquals(Color.RED, c1); + } + + @Test + void getHSBColor() { + } + + @Test + void getHSLColor() { + } + + @Test + void parseHexcode() { + } + + @Test + void morph() { + } + + @Test + void RGBtoHSL() { Color c; float[] hsl; @@ -101,45 +168,60 @@ public class TestColor { assertEquals(.5647f, hsl[2], .0001f); } - public static void main( String[] args ) { - new ColorPalette(); + @Test + void HSLtoRGB() { } - static class ColorPalette extends Zeichenmaschine { - public static final int SIZE = 10, COLORS = 16; + @Test + void testHSLtoRGB() { + } - public void setup() { - setSize(SIZE*COLORS, SIZE*COLORS); - setTitle("Colors"); + @Test + void copy() { + } - drawing.noStroke(); - drawing.setAnchor(NORTHWEST); + @Test + void getRGBA() { + Color yellow = new Color(255, 255, 0); + assertEquals(java.awt.Color.YELLOW.getRGB(), Color.YELLOW.getRGBA()); + } - int steps = (int) (255.0/COLORS); - Color c; - for( int i = 0; i < COLORS; i++ ) { - for( int j = 0; j < COLORS; j++ ) { - c = new Color(i * steps, j * steps, (i+j)/2 * steps); - drawing.setFillColor(c); - drawing.rect(i*SIZE, j*SIZE, SIZE, SIZE); - } - } - } + @Test + void getRed() { + } - public void draw() { - Color c = Color.HGGREEN; - drawing.setFillColor(c); - drawing.rect(0, 0, width/2, height); + @Test + void getGreen() { + } - for( int p = 10; p < 100; p += 10 ) { - drawing.setFillColor(c.brighter(p)); - drawing.rect(width / 2, 0, width / 2, height / 2); - drawing.setFillColor(c.darker(p)); - drawing.rect(width / 2, height / 2, width / 2, height / 2); + @Test + void getBlue() { + } - delay(1000); - } - } + @Test + void getAlpha() { + } + + @Test + void getJavaColor() { + assertEquals(java.awt.Color.YELLOW, Color.YELLOW.getJavaColor()); + assertEquals(new java.awt.Color(255, 31, 124), new Color(255, 31, 124).getJavaColor()); + } + + @Test + void brighter() { + } + + @Test + void testBrighter() { + } + + @Test + void darker() { + } + + @Test + void testDarker() { } } diff --git a/test/src/schule/ngb/zm/ConstantsTest.java b/src/test/java/schule/ngb/zm/ConstantsTest.java similarity index 100% rename from test/src/schule/ngb/zm/ConstantsTest.java rename to src/test/java/schule/ngb/zm/ConstantsTest.java diff --git a/test/src/schule/ngb/zm/OptionsTest.java b/src/test/java/schule/ngb/zm/OptionsTest.java similarity index 100% rename from test/src/schule/ngb/zm/OptionsTest.java rename to src/test/java/schule/ngb/zm/OptionsTest.java diff --git a/test/src/schule/ngb/zm/TestAttraction.java b/src/test/java/schule/ngb/zm/TestAttraction.java similarity index 100% rename from test/src/schule/ngb/zm/TestAttraction.java rename to src/test/java/schule/ngb/zm/TestAttraction.java diff --git a/test/src/schule/ngb/zm/TestDrawing.java b/src/test/java/schule/ngb/zm/TestDrawing.java similarity index 100% rename from test/src/schule/ngb/zm/TestDrawing.java rename to src/test/java/schule/ngb/zm/TestDrawing.java diff --git a/test/src/schule/ngb/zm/TestInput.java b/src/test/java/schule/ngb/zm/TestInput.java similarity index 100% rename from test/src/schule/ngb/zm/TestInput.java rename to src/test/java/schule/ngb/zm/TestInput.java diff --git a/test/src/schule/ngb/zm/TestShapes.java b/src/test/java/schule/ngb/zm/TestShapes.java similarity index 100% rename from test/src/schule/ngb/zm/TestShapes.java rename to src/test/java/schule/ngb/zm/TestShapes.java diff --git a/test/src/schule/ngb/zm/TestTurtle.java b/src/test/java/schule/ngb/zm/TestTurtle.java similarity index 100% rename from test/src/schule/ngb/zm/TestTurtle.java rename to src/test/java/schule/ngb/zm/TestTurtle.java diff --git a/test/src/schule/ngb/zm/VectorTest.java b/src/test/java/schule/ngb/zm/VectorTest.java similarity index 58% rename from test/src/schule/ngb/zm/VectorTest.java rename to src/test/java/schule/ngb/zm/VectorTest.java index d8ec662..d8608db 100644 --- a/test/src/schule/ngb/zm/VectorTest.java +++ b/src/test/java/schule/ngb/zm/VectorTest.java @@ -2,10 +2,79 @@ package schule.ngb.zm; import org.junit.jupiter.api.Test; +import java.awt.geom.Point2D; + import static org.junit.jupiter.api.Assertions.*; class VectorTest { + @Test + public void init() { + Vector vec; + + vec = new Vector(); + assertEquals(0.0, vec.x, 0.0); + assertEquals(0.0, vec.y, 0.0); + + vec = new Vector(4.5, 5.1); + assertEquals(4.5, vec.x, 0.0); + assertEquals(5.1, vec.y, 0.0); + + vec = new Vector(vec); + assertEquals(4.5, vec.x, 0.0); + assertEquals(5.1, vec.y, 0.0); + + vec = new Vector(Double.MAX_VALUE, Double.MIN_VALUE); + assertEquals(Double.MAX_VALUE, vec.x, 0.0); + assertEquals(Double.MIN_VALUE, vec.y, 0.0); + + vec = new Vector(new Point2D.Double(7.2, 3.5677)); + assertEquals(7.2, vec.x, 0.0); + assertEquals(3.5677, vec.y, 0.0); + + vec = new Vector(new Point2D.Float(7.2f, 3.5677f)); + assertEquals(7.2, vec.x, 0.0001); + assertEquals(3.5677, vec.y, 0.0001); + + vec.set(new Vector(5.1, 8.9)); + assertEquals(5.1, vec.x, 0.0001); + assertEquals(8.9, vec.y, 0.0001); + + Vector vec2 = vec.copy(); + assertNotSame(vec, vec2); + assertEquals(vec, vec2); + assertEquals(5.1, vec2.x, 0.0001); + assertEquals(8.9, vec2.y, 0.0001); + + assertEquals(vec, vec.set(100, 100)); + assertEquals(200, vec.set(200, 200).x, 0.0001); + assertEquals(8.9, vec.set(vec2).y, 0.0001); + + for( int i = 0; i < 50; i++ ) { + vec = Vector.random(); + assertTrue(vec.x >= 0); + assertTrue(vec.y >= 0); + assertTrue(vec.x < 100); + assertTrue(vec.y < 100); + } + + for( int i = 1; i < 50; i++ ) { + vec = Vector.random(0, i*10); + assertTrue(vec.x >= 0); + assertTrue(vec.y >= 0); + assertTrue(vec.x < i*10); + assertTrue(vec.y < i*10); + } + + for( int i = 1; i < 50; i++ ) { + vec = Vector.random(0, i*10, (i+1)*10, (i+2)*10); + assertTrue(vec.x >= 0); + assertTrue(vec.y >= (i+1)*10); + assertTrue(vec.x < i*10); + assertTrue(vec.y < (i+2)*10); + } + } + @Test void setLength() { Vector vec = new Vector(2.0, 5.4); diff --git a/test/src/schule/ngb/zm/shapes/ShapeTest.java b/src/test/java/schule/ngb/zm/shapes/ShapeTest.java similarity index 100% rename from test/src/schule/ngb/zm/shapes/ShapeTest.java rename to src/test/java/schule/ngb/zm/shapes/ShapeTest.java diff --git a/test/src/schule/ngb/zm/util/ValidatorTest.java b/src/test/java/schule/ngb/zm/util/ValidatorTest.java similarity index 100% rename from test/src/schule/ngb/zm/util/ValidatorTest.java rename to src/test/java/schule/ngb/zm/util/ValidatorTest.java diff --git a/test/res/WitchCraftIcons_122_t.PNG b/src/test/resources/WitchCraftIcons_122_t.PNG similarity index 100% rename from test/res/WitchCraftIcons_122_t.PNG rename to src/test/resources/WitchCraftIcons_122_t.PNG diff --git a/test/res/bluej-project/BluejTest.java b/test/res/bluej-project/BluejTest.java deleted file mode 100644 index 24948c6..0000000 --- a/test/res/bluej-project/BluejTest.java +++ /dev/null @@ -1,34 +0,0 @@ - -import schule.ngb.zm.Zeichenmaschine; - -import java.util.List; - -/** - * Beschreiben Sie hier die Klasse BluejTest. - * - * @author (Ihr Name) - * @version (eine Versionsnummer oder ein Datum) - */ -public class BluejTest extends Zeichenmaschine -{ - public void setup() { - if( !IN_BLUEJ ) { - drawing.clear(schule.ngb.zm.Color.HGRED); - } else { - drawing.clear(schule.ngb.zm.Color.HGGREEN); - - } - } - - public void listClasses() { - // find all classes in classpath - List allClasses = ClasspathInspector.getAllKnownClassNames(); - System.out.printf("There are %s classes available in the classpath\n", allClasses.size()); - - for (String clazz : allClasses) { - if( clazz.contains("Boot") || clazz.contains("Main") ) { - System.out.printf("%s\n", clazz); - } - } - } -} diff --git a/test/res/bluej-project/ClasspathInspector.java b/test/res/bluej-project/ClasspathInspector.java deleted file mode 100644 index 28f3029..0000000 --- a/test/res/bluej-project/ClasspathInspector.java +++ /dev/null @@ -1,283 +0,0 @@ - - -import java.io.File; -import java.io.FilenameFilter; -import java.io.Serializable; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.List; -import java.util.jar.JarEntry; -import java.util.jar.JarFile; - -/** - * Find classes in the classpath (reads JARs and classpath folders). - * - * @author Pål Brattberg, brattberg@gmail.com - * @see http://gist.github.com/pal - */ -@SuppressWarnings("unchecked") -public class ClasspathInspector { - static boolean DEBUG = false; - - - public static List getAllKnownClassNames() { - List classNames = new ArrayList(); - List classLocations = getClassLocationsForCurrentClasspath(); - for (File file : classLocations) { - classNames.addAll(getClassNamesFromPath(file)); - } - return classNames; - } - - public static List getAllKnownClasses() { - List classFiles = new ArrayList(); - List classLocations = getClassLocationsForCurrentClasspath(); - for (File file : classLocations) { - classFiles.addAll(getClassesFromPath(file)); - } - return classFiles; - } - - public static List getMatchingClasses(Class interfaceOrSuperclass) { - List matchingClasses = new ArrayList(); - List classes = getAllKnownClasses(); - log("checking %s classes", classes.size()); - for (Class clazz : classes) { - if (interfaceOrSuperclass.isAssignableFrom(clazz)) { - matchingClasses.add(clazz); - log("class %s is assignable from %s", interfaceOrSuperclass, clazz); - } - } - return matchingClasses; - } - - public static List getMatchingClasses(String validPackagePrefix, Class interfaceOrSuperclass) { - throw new IllegalStateException("Not yet implemented!"); - } - - public static List getMatchingClasses(String validPackagePrefix) { - throw new IllegalStateException("Not yet implemented!"); - } - - private static Collection getClassesFromPath(File path) { - if (path.isDirectory()) { - return getClassesFromDirectory(path); - } else { - return getClassesFromJarFile(path); - } - } - - private static Collection getClassNamesFromPath(File path) { - if (path.isDirectory()) { - return getClassNamesFromDirectory(path); - } else { - return getClassNamesFromJarFile(path); - } - } - - private static String fromFileToClassName(final String fileName) { - return fileName.substring(0, fileName.length() - 6).replaceAll("/|\\\\", "\\."); - } - - private static List getClassesFromJarFile(File path) { - List classes = new ArrayList(); - log("getClassesFromJarFile: Getting classes for " + path); - - try { - if (path.canRead()) { - JarFile jar = new JarFile(path); - Enumeration en = jar.entries(); - while (en.hasMoreElements()) { - JarEntry entry = en.nextElement(); - if (entry.getName().endsWith("class")) { - String className = fromFileToClassName(entry.getName()); - log("\tgetClassesFromJarFile: found " + className); - Class claz = Class.forName(className); - classes.add(claz); - } - } - } - } catch (Exception e) { - throw new RuntimeException("Failed to read classes from jar file: " + path, e); - } - - return classes; - } - - private static List getClassNamesFromJarFile(File path) { - List classes = new ArrayList<>(); - log("getClassNamesFromJarFile: Getting classes for " + path); - - try { - if (path.canRead()) { - JarFile jar = new JarFile(path); - Enumeration en = jar.entries(); - while (en.hasMoreElements()) { - JarEntry entry = en.nextElement(); - if (entry.getName().endsWith("class")) { - String className = fromFileToClassName(entry.getName()); - classes.add(className); - log("\tgetClassesFromJarFile: found " + className); - } - } - } - } catch (Exception e) { - throw new RuntimeException("Failed to read classnames from jar file: " + path, e); - } - - return classes; - } - - private static List getClassesFromDirectory(File path) { - List classes = new ArrayList(); - log("getClassesFromDirectory: Getting classes for " + path); - - // get jar files from top-level directory - List jarFiles = listFiles(path, new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".jar"); - } - }, false); - for (File file : jarFiles) { - classes.addAll(getClassesFromJarFile(file)); - } - - // get all class-files - List classFiles = listFiles(path, new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".class"); - } - }, true); - - // List urlList = new ArrayList(); - // List classNameList = new ArrayList(); - int substringBeginIndex = path.getAbsolutePath().length() + 1; - for (File classfile : classFiles) { - String className = classfile.getAbsolutePath().substring(substringBeginIndex); - className = fromFileToClassName(className); - log("Found class %s in path %s: ", className, path); - try { - classes.add(Class.forName(className)); - } catch (Throwable e) { - log("Couldn't create class %s. %s: ", className, e); - } - - } - - return classes; - } - - private static List getClassNamesFromDirectory(File path) { - List classes = new ArrayList<>(); - log("getClassNamesFromDirectory: Getting classes for " + path); - - // get jar files from top-level directory - List jarFiles = listFiles(path, new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".jar"); - } - }, false); - for (File file : jarFiles) { - classes.addAll(getClassNamesFromJarFile(file)); - } - - // get all class-files - List classFiles = listFiles(path, new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.endsWith(".class"); - } - }, true); - - // List urlList = new ArrayList(); - // List classNameList = new ArrayList(); - int substringBeginIndex = path.getAbsolutePath().length() + 1; - for (File classfile : classFiles) { - String className = classfile.getAbsolutePath().substring(substringBeginIndex); - className = fromFileToClassName(className); - log("Found class %s in path %s: ", className, path); - classes.add(className); - } - - return classes; - } - - private static List listFiles(File directory, FilenameFilter filter, boolean recurse) { - List files = new ArrayList(); - File[] entries = directory.listFiles(); - - // Go over entries - for (File entry : entries) { - // If there is no filter or the filter accepts the - // file / directory, add it to the list - if (filter == null || filter.accept(directory, entry.getName())) { - files.add(entry); - } - - // If the file is a directory and the recurse flag - // is set, recurse into the directory - if (recurse && entry.isDirectory()) { - files.addAll(listFiles(entry, filter, recurse)); - } - } - - // Return collection of files - return files; - } - - public static List getClassLocationsForCurrentClasspath() { - List urls = new ArrayList(); - String javaClassPath = System.getProperty("java.class.path"); - if (javaClassPath != null) { - for (String path : javaClassPath.split(File.pathSeparator)) { - urls.add(new File(path)); - } - } - return urls; - } - - // todo: this is only partial, probably - public static URL normalize(URL url) throws MalformedURLException { - String spec = url.getFile(); - - // get url base - remove everything after ".jar!/??" , if exists - final int i = spec.indexOf("!/"); - if (i != -1) { - spec = spec.substring(0, spec.indexOf("!/")); - } - - // uppercase windows drive - url = new URL(url, spec); - final String file = url.getFile(); - final int i1 = file.indexOf(':'); - if (i1 != -1) { - String drive = file.substring(i1 - 1, 2).toUpperCase(); - url = new URL(url, file.substring(0, i1 - 1) + drive + file.substring(i1)); - } - - return url; - } - - private static void log(String pattern, final Object... args) { - if (DEBUG) - System.out.printf(pattern + "\n", args); - } - - public static void main(String[] args) { - // find all classes in classpath - List allClasses = ClasspathInspector.getAllKnownClasses(); - System.out.printf("There are %s classes available in the classpath\n", allClasses.size()); - - // find all classes that implement/subclass an interface/superclass - List serializableClasses = ClasspathInspector.getMatchingClasses(Serializable.class); - for (Class clazz : serializableClasses) { - System.out.printf("%s is Serializable\n", clazz); - } - } -} diff --git a/test/res/bluej-project/package.bluej b/test/res/bluej-project/package.bluej deleted file mode 100644 index c3e740b..0000000 --- a/test/res/bluej-project/package.bluej +++ /dev/null @@ -1,42 +0,0 @@ -#BlueJ package file -dependency1.from=BluejTest -dependency1.to=ClasspathInspector -dependency1.type=UsesDependency -editor.fx.0.height=0 -editor.fx.0.width=0 -editor.fx.0.x=0 -editor.fx.0.y=0 -objectbench.height=94 -objectbench.width=776 -package.divider.horizontal=0.6 -package.divider.vertical=0.8305369127516778 -package.editor.height=488 -package.editor.width=661 -package.editor.x=374 -package.editor.y=158 -package.frame.height=660 -package.frame.width=800 -package.numDependencies=1 -package.numTargets=2 -package.showExtends=true -package.showUses=true -project.charset=UTF-8 -readme.height=60 -readme.name=@README -readme.width=48 -readme.x=10 -readme.y=10 -target1.height=70 -target1.name=BluejTest -target1.showInterface=false -target1.type=ClassTarget -target1.width=120 -target1.x=70 -target1.y=10 -target2.height=70 -target2.name=ClasspathInspector -target2.showInterface=false -target2.type=ClassTarget -target2.width=130 -target2.x=380 -target2.y=30 diff --git a/test/src/schule/ngb/zm/ColorTest.java b/test/src/schule/ngb/zm/ColorTest.java deleted file mode 100644 index 6b02683..0000000 --- a/test/src/schule/ngb/zm/ColorTest.java +++ /dev/null @@ -1,135 +0,0 @@ -package schule.ngb.zm; - -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -class ColorTest { - - - @Test - void testEquals() { - Color c1 = new Color(254, 98, 12); - Color c2 = new Color(254, 98, 12); - assertNotSame(c1, c2); - assertEquals(c1, c2); - assertEquals(c1, c1); - c2 = new Color(c1); - assertNotSame(c1, c2); - assertEquals(c1, c2); - - assertEquals(Color.YELLOW, java.awt.Color.YELLOW); - assertNotEquals(java.awt.Color.YELLOW, Color.YELLOW); - } - - @Test - void construct() { - Color c; - // Empty color is white - c = new Color(); - assertEquals(c, Color.BLACK); - // One arg is shade of gray - c = new Color(255); - assertEquals(c, Color.WHITE); - c = new Color(0); - assertEquals(c, Color.BLACK); - c = new Color(64); - assertEquals(c, Color.DARKGRAY); - c = new Color(192); - assertEquals(c, Color.LIGHTGRAY); - // RGB colors - c = new Color(0,0,0); - assertEquals(c, Color.BLACK); - c = new Color(255,0,0); - assertEquals(c, Color.RED); - c = new Color(0,255,0); - assertEquals(c, Color.GREEN); - c = new Color(0,0,255); - assertEquals(c, Color.BLUE); - // From java.awt.Color - c = new Color(java.awt.Color.YELLOW); - assertEquals(c, Color.YELLOW); - } - - @Test - void getRGBColor() { - Color c1 = Color.getRGBColor(0xFFFF0000); - assertEquals(Color.RED, c1); - } - - @Test - void getHSBColor() { - } - - @Test - void getHSLColor() { - } - - @Test - void parseHexcode() { - } - - @Test - void morph() { - } - - @Test - void RGBtoHSL() { - } - - @Test - void HSLtoRGB() { - } - - @Test - void testHSLtoRGB() { - } - - @Test - void copy() { - } - - @Test - void getRGBA() { - assertEquals(java.awt.Color.YELLOW.getRGB(), Color.YELLOW.getRGBA()); - } - - @Test - void getRed() { - } - - @Test - void getGreen() { - } - - @Test - void getBlue() { - } - - @Test - void getAlpha() { - } - - @Test - void getColor() { - assertEquals(java.awt.Color.YELLOW, Color.YELLOW.getJavaColor()); - assertEquals(new java.awt.Color(255, 31, 124), new Color(255, 31, 124).getJavaColor()); - } - - @Test - void brighter() { - } - - @Test - void testBrighter() { - } - - @Test - void darker() { - } - - @Test - void testDarker() { - } - -} diff --git a/test/src/schule/ngb/zm/TestVector.java b/test/src/schule/ngb/zm/TestVector.java deleted file mode 100644 index ae2db3d..0000000 --- a/test/src/schule/ngb/zm/TestVector.java +++ /dev/null @@ -1,112 +0,0 @@ -package schule.ngb.zm; - -import org.junit.Test; - -import java.awt.geom.Point2D; - -import static org.junit.Assert.*; - -public class TestVector { - - @Test - public void testInit() { - Vector vec; - - vec = new Vector(); - assertEquals(0.0, vec.x, 0.0); - assertEquals(0.0, vec.y, 0.0); - - vec = new Vector(4.5, 5.1); - assertEquals(4.5, vec.x, 0.0); - assertEquals(5.1, vec.y, 0.0); - - vec = new Vector(vec); - assertEquals(4.5, vec.x, 0.0); - assertEquals(5.1, vec.y, 0.0); - - vec = new Vector(Double.MAX_VALUE, Double.MIN_VALUE); - assertEquals(Double.MAX_VALUE, vec.x, 0.0); - assertEquals(Double.MIN_VALUE, vec.y, 0.0); - - vec = new Vector(new Point2D.Double(7.2, 3.5677)); - assertEquals(7.2, vec.x, 0.0); - assertEquals(3.5677, vec.y, 0.0); - - vec = new Vector(new Point2D.Float(7.2f, 3.5677f)); - assertEquals(7.2, vec.x, 0.0001); - assertEquals(3.5677, vec.y, 0.0001); - - vec.set(new Vector(5.1, 8.9)); - assertEquals(5.1, vec.x, 0.0001); - assertEquals(8.9, vec.y, 0.0001); - - Vector vec2 = vec.copy(); - assertNotSame(vec, vec2); - assertEquals(vec, vec2); - assertEquals(5.1, vec2.x, 0.0001); - assertEquals(8.9, vec2.y, 0.0001); - - assertEquals(vec, vec.set(100, 100)); - assertEquals(200, vec.set(200, 200).x, 0.0001); - assertEquals(8.9, vec.set(vec2).y, 0.0001); - - for( int i = 0; i < 50; i++ ) { - vec = Vector.random(); - assertTrue(vec.x >= 0); - assertTrue(vec.y >= 0); - assertTrue(vec.x < 100); - assertTrue(vec.y < 100); - } - - for( int i = 1; i < 50; i++ ) { - vec = Vector.random(0, i*10); - assertTrue(vec.x >= 0); - assertTrue(vec.y >= 0); - assertTrue(vec.x < i*10); - assertTrue(vec.y < i*10); - } - - for( int i = 1; i < 50; i++ ) { - vec = Vector.random(0, i*10, (i+1)*10, (i+2)*10); - assertTrue(vec.x >= 0); - assertTrue(vec.y >= (i+1)*10); - assertTrue(vec.x < i*10); - assertTrue(vec.y < (i+2)*10); - } - } - - @Test - public void testMath() { - Vector vec1, vec2; - - vec1 = new Vector(100, 0); - vec1.scale(0.0); - vec2 = new Vector(0, 0); - assertEquals(vec2, vec1); - - vec1.add(100, 50); - assertEquals(100, vec1.x, 0.0); - assertEquals(50, vec1.y, 0.0); - - vec2.sub(50, 100); - assertEquals(-50, vec2.x, 0.0); - assertEquals(-100, vec2.y, 0.0); - - vec2.scale(1.5); - assertEquals(-75, vec2.x, 0.0001); - assertEquals(-150, vec2.y, 0.0001); - - assertEquals(100, vec1.set(100,0).length(), 0.0001); - assertEquals(10000, vec1.lengthSq(), 0.0001); - assertEquals(Math.sqrt(50*50 + 60*60), vec1.set(50,60).length(), 0.0001); - assertEquals(1.0, vec1.set(100,0).normalize().length(), 0.0001); - assertEquals(1.0, Vector.random().normalize().length(), 0.0001); - } - - - @Test - public void testStaticMath() { - - } - -}