mirror of
https://github.com/jneug/zeichenmaschine.git
synced 2026-10-12 09:56:33 +02:00
Compare commits
12 Commits
836571ca95
...
936043bf85
| Author | SHA1 | Date | |
|---|---|---|---|
| 936043bf85 | |||
| d75f67c0fa | |||
| adbc29dabe | |||
| b687483e6d | |||
| 19bacd15e9 | |||
| 2d4abf6f0d | |||
| cefe7c8cfa | |||
| b04e68c7bd | |||
| 25ce3a35e9 | |||
| 44d0f79c6c | |||
| 43195aa63c | |||
| 6cc23de620 |
@@ -7,13 +7,16 @@ und diese Projekt folgt [Semantic Versioning](https://semver.org/spec/v2.0.0.htm
|
||||
## [Unreleased]
|
||||
|
||||
## Added
|
||||
- Dokumentation `EventDispatcher`.
|
||||
- Dokumentation erweitert.
|
||||
- Caching-Mechanismen in Klasse `util.Cache` ausgelagert.
|
||||
- `util.io.ImageLoader` und `util.io.FontLoader` verwenden `Cache`.
|
||||
|
||||
## Changed
|
||||
- Die Methoden in `Validator` erwarten nun als zweiten Parameter den Namen des Parameters, der geprüft wird.
|
||||
|
||||
## Fixed
|
||||
- `Constants.choice(int...)` und `Constants.choice(double...)` wiederhergestellt.
|
||||
- Timing-Problem beim Aufruf von `AudioListener.playbackStopped()` in `Sound` behoben.
|
||||
|
||||
## Removed
|
||||
- `layers.Shape2DLayer` ist nur noch im Test-Paket verfügbar.
|
||||
|
||||
57
build.gradle
57
build.gradle
@@ -33,24 +33,16 @@ dependencies {
|
||||
testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.8.1'
|
||||
}
|
||||
|
||||
javadoc {
|
||||
options {
|
||||
encoding = "UTF-8"
|
||||
overview = "src/main/java/overview.html"
|
||||
// title = "Die Zeichenmaschine"
|
||||
|
||||
// options.links 'https://docs.oracle.com/javase/8/docs/api/'
|
||||
// options.links 'https://docs.oracle.com/javaee/7/api'
|
||||
options.links 'https://docs.oracle.com/en/java/javase/11/docs/api'
|
||||
jar {
|
||||
manifest {
|
||||
attributes 'Class-Path': '.'
|
||||
}
|
||||
options.addStringOption("charset", "UTF-8")
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
tasks.register('jarMP3SPI', Jar) {
|
||||
group "build"
|
||||
description "Build jar with MP3SPI included"
|
||||
|
||||
archiveClassifier = 'mp3spi'
|
||||
duplicatesStrategy = 'exclude'
|
||||
// archivesBaseName = 'zeichenmaschine-mp3spi'
|
||||
@@ -61,8 +53,45 @@ tasks.register('jarMP3SPI', Jar) {
|
||||
}
|
||||
|
||||
task buildAll {
|
||||
group "build"
|
||||
description "Build all jar packages"
|
||||
|
||||
dependsOn 'jar'
|
||||
dependsOn 'jarMP3SPI'
|
||||
dependsOn 'sourcesJar'
|
||||
dependsOn 'javadocJar'
|
||||
}
|
||||
|
||||
javadoc {
|
||||
options {
|
||||
encoding = "UTF-8"
|
||||
overview = "src/resources/java/overview.html"
|
||||
// title = "Die Zeichenmaschine"
|
||||
|
||||
// options.links 'https://docs.oracle.com/javase/8/docs/api/'
|
||||
// options.links 'https://docs.oracle.com/javaee/7/api'
|
||||
options.links 'https://docs.oracle.com/en/java/javase/11/docs/api'
|
||||
}
|
||||
options.addStringOption("charset", "UTF-8")
|
||||
}
|
||||
|
||||
task mkdocs(type: Exec) {
|
||||
group "documentation"
|
||||
description "Build MKDocs site"
|
||||
|
||||
workingDir "${projectDir}"
|
||||
commandLine ".venv/bin/python", "-m", "mkdocs", "build"
|
||||
}
|
||||
|
||||
task buildDocs {
|
||||
group "documentation"
|
||||
description "Run all documentation tasks"
|
||||
|
||||
dependsOn 'javadoc'
|
||||
dependsOn 'javadocJar'
|
||||
dependsOn 'mkdocs'
|
||||
}
|
||||
|
||||
test {
|
||||
useJUnitPlatform()
|
||||
}
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
|
||||
<figure markdown>
|
||||
{ width=128 }
|
||||
</figure>
|
||||
@@ -9,10 +8,11 @@ Informatikunterricht.</h2>
|
||||
|
||||
## Projektidee
|
||||
|
||||
Die **Zeichenmaschine** ist eine für den Informatikunterricht entwickelte Bibliothek,
|
||||
die unter anderem an [Processing](https://processing.org/) angelehnt ist. Die
|
||||
Bibliothek soll einige der üblichen Anfängerschwierigkeiten mit Java vereinfachen
|
||||
und für Schülerinnen und Schüler im Unterricht nutzbar machen.
|
||||
Die **Zeichenmaschine** ist eine für den Informatikunterricht entwickelte
|
||||
Bibliothek, die unter anderem an [Processing](https://processing.org/) angelehnt
|
||||
ist. Die Bibliothek soll einige der üblichen Anfängerschwierigkeiten mit Java
|
||||
vereinfachen und grafische Ausgaben für Schülerinnen und Schüler im Unterricht
|
||||
leichter nutzbar machen.
|
||||
|
||||
!!! warning
|
||||
|
||||
@@ -29,12 +29,39 @@ und für Schülerinnen und Schüler im Unterricht nutzbar machen.
|
||||
(Gleiches gilt für diese Webseite zum Projekt.)
|
||||
|
||||
## Dokumentation
|
||||
|
||||
* [Schnellstart](quickstart.md)
|
||||
* [Installation](installation.md)
|
||||
* {{ javadoc_link() }}
|
||||
|
||||
## Über die Zeichenmaschine
|
||||
|
||||
Die _Zeichenmaschine_ ist aus dem Wunsch entstanden, nach einer Einführung in
|
||||
die Grundlagen der Programmiersprache Java mit Processing, einen Übergang zur
|
||||
objektorientierten Modellierung und Programmierung mit BlueJ zu leichter zu
|
||||
ermöglichen. Mit Processing kann zwar auch objektorientiert programmiert werden,
|
||||
aber mit Blick auf die Sekundarstufe II in NRW ist ein Wechsel zu einer
|
||||
generellen Programmierumgebung wie BlueJ wünschenswert.
|
||||
|
||||
Die Motivation von Processing, schnell grafische Ergebnisse der eigenen
|
||||
Programme zu sehen, sollte aber für den Übergang erhalten bleiben. So ist eine
|
||||
kleine Bibliothek mit minimalen Abhängigkeiten entstanden, die an Processing
|
||||
angelehnt einfache Schnittstellen bereitstellte, um Programmen eine grafische
|
||||
Ausgabe zu ermöglichen, ohne viel "Boilerplate" Code schreiben zu müssen.
|
||||
|
||||
Aus diesen Anfängen ist nach und nach eine umfassende Grafikbibliothek
|
||||
entstanden, die als _Zeichenmaschine_ veröffentlicht wurde.
|
||||
|
||||
### Was die Zeichenmaschine nicht ist
|
||||
|
||||
Die Bibliothek hat nicht den Anspruch, ein Konkurrent zu Processing oder
|
||||
anderen, seit Jahren etablierten und ausgereiften, Grafiksystemen zu sein. Vor
|
||||
allem ist die _Zeichenmaschine_ keine vollwertige Game Engine, die auf die
|
||||
Ausführung komplexer Spiele spezialisiert ist. Für diese Zwecke gibt es genügend
|
||||
Alternativen, von deren Nutzung gar nicht abgeraten werden soll.
|
||||
|
||||
## Aufbau der Zeichenmaschine
|
||||
|
||||
!!! info
|
||||
|
||||
In der Zeichenmaschine werden bewusst nur englischsprachige Bezeichner für
|
||||
|
||||
@@ -67,7 +67,7 @@ public class Constants {
|
||||
/**
|
||||
* Patchversion der Zeichenmaschine.
|
||||
*/
|
||||
public static final int APP_VERSION_REV = 32;
|
||||
public static final int APP_VERSION_REV = 34;
|
||||
|
||||
/**
|
||||
* Version der Zeichenmaschine als Text-String.
|
||||
|
||||
@@ -2,6 +2,7 @@ package schule.ngb.zm;
|
||||
|
||||
import schule.ngb.zm.util.Log;
|
||||
import schule.ngb.zm.util.Validator;
|
||||
import schule.ngb.zm.util.io.ImageLoader;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.swing.*;
|
||||
@@ -10,6 +11,7 @@ import java.awt.event.KeyAdapter;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.awt.event.KeyListener;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -174,12 +176,14 @@ public class Zeichenfenster extends JFrame {
|
||||
// Das Icon des Fensters ändern
|
||||
try {
|
||||
if( Zeichenmaschine.MACOS ) {
|
||||
URL iconUrl = Zeichenmaschine.class.getResource("icon_512.png");
|
||||
if( iconUrl != null ) {
|
||||
Image icon = ImageIO.read(iconUrl);
|
||||
InputStream iconStream = this.getClass().getResourceAsStream("icon_512.png");
|
||||
if( iconStream != null ) {
|
||||
Image icon = ImageIO.read(iconStream);
|
||||
// Dock Icon in macOS setzen
|
||||
Taskbar taskbar = Taskbar.getTaskbar();
|
||||
taskbar.setIconImage(icon);
|
||||
} else {
|
||||
LOG.warn("Could not load dock-icon");
|
||||
}
|
||||
} else {
|
||||
ArrayList<Image> icons = new ArrayList<>(4);
|
||||
@@ -190,8 +194,12 @@ public class Zeichenfenster extends JFrame {
|
||||
}
|
||||
}
|
||||
|
||||
if( icons.isEmpty() ) {
|
||||
LOG.warn("Could not load dock-icon");
|
||||
} else {
|
||||
this.setIconImages(icons);
|
||||
}
|
||||
}
|
||||
} catch( IllegalArgumentException | IOException e ) {
|
||||
LOG.warn("Could not load image icons: %s", e.getMessage());
|
||||
} catch( SecurityException | UnsupportedOperationException macex ) {
|
||||
|
||||
@@ -797,6 +797,7 @@ public class Zeichenmaschine extends Constants {
|
||||
BufferedImage img = ImageLoader.createImage(canvas.getWidth(), canvas.getHeight());
|
||||
|
||||
Graphics2D g = img.createGraphics();
|
||||
// TODO: Transparente Hintergründe beim Speichern von png erlauben
|
||||
g.setColor(DEFAULT_BACKGROUND.getJavaColor());
|
||||
g.fillRect(0, 0, img.getWidth(), img.getHeight());
|
||||
canvas.draw(g);
|
||||
|
||||
@@ -923,12 +923,43 @@ public class DrawingLayer extends Layer implements Strokeable, Fillable {
|
||||
}
|
||||
}
|
||||
|
||||
public void curveTo( double ctrlX, double ctrlY, double x, double y ) {
|
||||
if( !pathStarted ) {
|
||||
path.moveTo(x, y);
|
||||
pathStarted = true;
|
||||
} else {
|
||||
path.quadTo(
|
||||
ctrlX, ctrlY,
|
||||
x, y
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
public void curveTo( double ctrlX1, double ctrlY1, double ctrlX2, double ctrlY2, double x, double y ) {
|
||||
if( !pathStarted ) {
|
||||
path.moveTo(x, y);
|
||||
pathStarted = true;
|
||||
} else {
|
||||
path.curveTo(
|
||||
ctrlX1, ctrlY1,
|
||||
ctrlX2, ctrlY2,
|
||||
x, y
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Beendet eine zuvor {@link #beginShape() begonnene} Freihand-Form und
|
||||
* zeichent sie auf die Zeichenebene.
|
||||
*/
|
||||
public void endShape() {
|
||||
endShape(CLOSED);
|
||||
}
|
||||
|
||||
public void endShape( Options.PathType closingType ) {
|
||||
if( closingType == Options.PathType.CLOSED ) {
|
||||
path.closePath();
|
||||
}
|
||||
path.trimToSize();
|
||||
pathStarted = false;
|
||||
|
||||
|
||||
@@ -235,8 +235,8 @@ public class Sound implements Audio {
|
||||
}
|
||||
|
||||
/**
|
||||
* Lädt falls nötig den {@link Clip} für die
|
||||
* {@link #audioSource Audioquelle} und startet die Wiedergabe.
|
||||
* Lädt, falls nötig, den {@link Clip} für die
|
||||
* {@link #audioSource Audioquelle}.
|
||||
*
|
||||
* @return {@code true}, wenn der Clip geöffnet werden konnte, {@code false}
|
||||
* sonst.
|
||||
@@ -264,10 +264,6 @@ public class Sound implements Audio {
|
||||
}
|
||||
} else if( event.getType() == LineEvent.Type.STOP ) {
|
||||
playbackStopped();
|
||||
|
||||
if( eventDispatcher != null ) {
|
||||
eventDispatcher.dispatchEvent("stop", Sound.this);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -313,6 +309,10 @@ public class Sound implements Audio {
|
||||
private void playbackStopped() {
|
||||
playing = false;
|
||||
|
||||
if( eventDispatcher != null ) {
|
||||
eventDispatcher.dispatchEvent("stop", Sound.this);
|
||||
}
|
||||
|
||||
if( disposeAfterPlay ) {
|
||||
this.dispose();
|
||||
disposeAfterPlay = false;
|
||||
|
||||
@@ -20,6 +20,12 @@ import java.util.stream.Collectors;
|
||||
* Collector gelöscht worden sein kann.
|
||||
* <p>
|
||||
* Als interne Map wird einen {@link ConcurrentHashMap} verwendet.
|
||||
* <p>
|
||||
* Ein passender Cache wird mittels der Fabrikmethoden {@link #newSoftCache()}
|
||||
* und {@link #newWeakCache()} erstellt.
|
||||
* <pre><code>
|
||||
* Cache<String, Image> imageCache = Cache.newSoftCache();
|
||||
* </code></pre>
|
||||
*
|
||||
* @param <K> Der Typ der Schlüssel.
|
||||
* @param <V> Der Typ der Objekte.
|
||||
@@ -70,10 +76,6 @@ public final class Cache<K, V> implements Map<K, V> {
|
||||
return cache.isEmpty();
|
||||
}
|
||||
|
||||
private boolean containsRef( Object key ) {
|
||||
return cache.containsKey(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean containsKey( Object key ) {
|
||||
return cache.containsKey(key) && cache.get(key).get() != null;
|
||||
@@ -93,17 +95,33 @@ public final class Cache<K, V> implements Map<K, V> {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void nocache( K key ) {
|
||||
/**
|
||||
* Deaktiviert das Caching für den angegebenen Schlüssel.
|
||||
* <p>
|
||||
* Folgende Aufrufe von {@link #put(Object, Object)} mit demselben Schlüssel
|
||||
* haben keinen Effekt. Um das Caching wieder zu aktivieren, muss
|
||||
* {@link #remove(Object)} mit dem Schlüssel aufgerufen werden,
|
||||
*
|
||||
* @param key Der Schlüssel.
|
||||
*/
|
||||
public void disableCache( K key ) {
|
||||
cache.put(key, NOCACHE);
|
||||
}
|
||||
|
||||
public boolean isNocache( K key ) {
|
||||
/**
|
||||
* Prüft, ob der für den angegebenen Schlüssel zuvor
|
||||
* {@link #disableCache(Object)} aufgerufen wurde.
|
||||
*
|
||||
* @param key Der Schlüssel.
|
||||
* @return {@code true}, wenn der Schlüssel nicht gespeichert wird.
|
||||
*/
|
||||
public boolean isCachingDisabled( K key ) {
|
||||
return cache.get(key) == NOCACHE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public V put( K key, V value ) {
|
||||
if( !isNocache(key) ) {
|
||||
if( !isCachingDisabled(key) ) {
|
||||
V prev = remove(key);
|
||||
cache.put(key, refSupplier.apply(value));
|
||||
return prev;
|
||||
|
||||
@@ -5,7 +5,7 @@ import java.util.List;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
/**
|
||||
* Eine Helferklasse, um Dinge zu zählen.
|
||||
* Eine Hilfsklasse, um Dinge zu zählen.
|
||||
* <p>
|
||||
* Im einfachsten Fall kann der Zähler als geteilte Zählvariable genutzt werden,
|
||||
* die mit {@link #inc()} und {@link #dec()} aus verschiedenen Objekten oder
|
||||
|
||||
@@ -28,7 +28,7 @@ import static java.lang.Math.log;
|
||||
import static schule.ngb.zm.Constants.random;
|
||||
|
||||
/**
|
||||
* Eine Helferklasse, um zufällige Beispieldaten zu erzeugen.
|
||||
* Eine Hilfsklasse, um zufällige Beispieldaten zu erzeugen.
|
||||
* <p>
|
||||
* Die Klasse kann verschiedene Arten realistischer Beispieldaten erzeugen.
|
||||
* Unter anderem Namen, E-Mail-Adressen, Passwörter oder Platzhalter-Bilder.
|
||||
|
||||
@@ -3,7 +3,7 @@ package schule.ngb.zm.util;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* Helferklasse zur Zeitmessung im Nanosekundenbereich.
|
||||
* Hilfsklasse zur Zeitmessung im Nanosekundenbereich.
|
||||
* <p>
|
||||
* Mit einem {@code Timer} kann zum Beispiel die Laufzeit eines Algorithmus
|
||||
* gemessen werden. Wie eine echte Stoppuhr läuft der {@code Timer} weiter, wenn
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Dieses Paket enthält Helferklassen, die das Listener-Entwurfsmuster
|
||||
* Dieses Paket enthält Hilfsklassen, die das Listener-Entwurfsmuster
|
||||
* umsetzen.
|
||||
*/
|
||||
package schule.ngb.zm.util.events;
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.util.List;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* Helferklasse, um Textdateien in verschiedenen Formaten einzulesen.
|
||||
* Hilfsklasse, um Textdateien in verschiedenen Formaten einzulesen.
|
||||
*/
|
||||
@SuppressWarnings( "unused" )
|
||||
public final class FileLoader {
|
||||
|
||||
@@ -14,7 +14,7 @@ import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Eine Helferklasse mit Klassenmethoden, um Schriftarten zu laden.
|
||||
* Eine Hilfsklasse mit Klassenmethoden, um Schriftarten zu laden.
|
||||
* <p>
|
||||
* Schriftarten können von verschiedenen Quellen geladen werden. Schriftarten,
|
||||
* die aus Dateien geladen wurden, werden in einem internen Cache gespeichert
|
||||
|
||||
@@ -16,10 +16,9 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.ref.SoftReference;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Eine Helferklasse mit Klassenmethoden, um Bilder zu laden.
|
||||
* Eine Hilfsklasse mit Klassenmethoden, um Bilder zu laden.
|
||||
* <p>
|
||||
* Bilder können von verschiedenen Quellen als {@link Image} geladen werden. Die
|
||||
* Objekte werden in einem internen Cache gespeichert und nachfolgende Versuche,
|
||||
@@ -71,8 +70,8 @@ public final class ImageLoader {
|
||||
Validator.requireNotNull(source, "Image source may not be null");
|
||||
Validator.requireNotEmpty(source, "Image source may not be empty.");
|
||||
|
||||
if( caching && isCached(source) ) {
|
||||
return getCache(source);
|
||||
if( caching && imageCache.containsKey(source) ) {
|
||||
return imageCache.get(source);
|
||||
}
|
||||
|
||||
BufferedImage img = null;
|
||||
@@ -83,7 +82,7 @@ public final class ImageLoader {
|
||||
img = ImageIO.read(in);
|
||||
|
||||
if( caching && img != null ) {
|
||||
putCache(source, img);
|
||||
imageCache.put(source, img);
|
||||
}
|
||||
} catch( IOException ioex ) {
|
||||
LOG.error(ioex, "Error loading image file from source <%s>.", source);
|
||||
@@ -111,7 +110,7 @@ public final class ImageLoader {
|
||||
public static boolean preloadImage( String name, String source ) {
|
||||
BufferedImage img = loadImage(source, true);
|
||||
if( img != null ) {
|
||||
putCache(name, img);
|
||||
imageCache.put(name, img);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -132,7 +131,7 @@ public final class ImageLoader {
|
||||
* @param img ZU speicherndes Bild.
|
||||
*/
|
||||
public static void preloadImage( String name, BufferedImage img ) {
|
||||
putCache(name, img);
|
||||
imageCache.put(name, img);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -156,30 +155,6 @@ public final class ImageLoader {
|
||||
imageCache.remove(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Speichert ein Bild als {@link SoftReference} im Cache.
|
||||
*
|
||||
* @param name Name des Bildes im Zwischenspeicher.
|
||||
* @param img Das zu speichernde Bild.
|
||||
*/
|
||||
private static void putCache( final String name, final BufferedImage img ) {
|
||||
imageCache.put(name, img);
|
||||
}
|
||||
|
||||
/**
|
||||
* Holt ein Bild aus dem Cache.
|
||||
* <p>
|
||||
* Prüft nicht, ob ein Bild vorhanden ist. Dies sollte vom Aufrufenden
|
||||
* übernommen werden, da sonst eine {@link NullPointerException} erzeugt
|
||||
* werden kann.
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
private static BufferedImage getCache( final String name ) {
|
||||
return imageCache.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Deaktiviert den Cache für die angegebene Quelle.
|
||||
* <p>
|
||||
@@ -189,14 +164,14 @@ public final class ImageLoader {
|
||||
*
|
||||
* @param name Die Quelle des Bildes.
|
||||
*/
|
||||
public static void preventCache( final String name ) {
|
||||
imageCache.nocache(name);
|
||||
public static void disableCache( final String name ) {
|
||||
imageCache.disableCache(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Leer den Cache und löschte alle bisher gespeicherten Bilder.
|
||||
* <p>
|
||||
* Auch vorher mit {@link #preventCache(String)} verhinderte Caches werden
|
||||
* Auch vorher mit {@link #disableCache(String)} verhinderte Caches werden
|
||||
* gelöscht und müssen neu gesetzt werden.
|
||||
*/
|
||||
public static void clearCache() {
|
||||
|
||||
@@ -13,7 +13,7 @@ import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Helferklasse, um {@link InputStream}s für Ressourcen zu erhalten.
|
||||
* Hilfsklasse, um {@link InputStream}s für Ressourcen zu erhalten.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class ResourceStreamProvider {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Dieses Paket enthält Helferklassen, um Ressourcen aus verschiedenen Quellen
|
||||
* Dieses Paket enthält Hilfsklassen, um Ressourcen aus verschiedenen Quellen
|
||||
* zu laden.
|
||||
*/
|
||||
package schule.ngb.zm.util.io;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
* Dieses Paket enthält Helferklassen für verschiedene Einsatzzwecke.
|
||||
* Dieses Paket enthält Hilfsklassen für verschiedene Einsatzzwecke.
|
||||
*/
|
||||
package schule.ngb.zm.util;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Dieses Paket enthält Helferklassen zur Verarbeitung paralleler Aufgaben
|
||||
* Dieses Paket enthält Hilfsklassen zur Ausführung paralleler Aufgaben
|
||||
* innerhalb der Zeichenmaschine.
|
||||
*/
|
||||
package schule.ngb.zm.util.tasks;
|
||||
|
||||
Reference in New Issue
Block a user