From 5f50c63489664e14a2d039519c9249fb070fa51b Mon Sep 17 00:00:00 2001
From: tobias <thinkdifferent055@gmail.com>
Date: Tue, 24 Nov 2020 21:24:50 +0100
Subject: [PATCH] #169 - Add extra option to enable/disable fade out on eof

---
 .../playpad/pad/content/AudioContent.java     |  6 ++--
 .../pad/PlayerPadTabViewController.java       |  8 +++---
 .../profile/PlayerTabViewController.java      |  2 +-
 .../settings/FadeViewController.java          | 18 +++++++-----
 .../src/main/resources/lang/ui_de.properties  |  5 ++--
 .../resources/view/settings/FadeView.fxml     |  2 ++
 .../de/tobias/playpad/pad/PadSettings.java    | 10 +++----
 .../playpad/pad/PadSettingsSerializer.java    |  4 +--
 .../java/de/tobias/playpad/pad/fade/Fade.java | 18 ++++++------
 .../de/tobias/playpad/pad/fade/Fadeable.java  |  4 +++
 .../listener/PadFadeDurationListener.java     | 21 +++++++-------
 .../playpad/profile/ProfileSettings.java      | 10 +++----
 .../settings/{Fade.java => FadeSettings.java} | 28 ++++++++++++++-----
 13 files changed, 81 insertions(+), 55 deletions(-)
 rename PlayWallCore/src/main/java/de/tobias/playpad/settings/{Fade.java => FadeSettings.java} (81%)

diff --git a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java
index 426d058b..d7a2663f 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/pad/content/AudioContent.java
@@ -33,10 +33,10 @@ public class AudioContent extends PadContent implements Pauseable, Durationable,
 	private ObjectProperty<Duration> durationProperty = new SimpleObjectProperty<>();
 	private ObjectProperty<Duration> positionProperty = new SimpleObjectProperty<>();
 
-	private ChangeListener<Number> volumeListener;
-	private ChangeListener<Number> rateListener;
+	private final ChangeListener<Number> volumeListener;
+	private final ChangeListener<Number> rateListener;
 
-	private Fade fade;
+	private final Fade fade;
 
 	AudioContent(String type, Pad pad) {
 		super(pad);
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java
index 67d71214..647b513e 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/pad/PlayerPadTabViewController.java
@@ -4,7 +4,7 @@ import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.Strings;
 import de.tobias.playpad.pad.Pad;
 import de.tobias.playpad.pad.PadSettings;
-import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.FadeSettings;
 import de.tobias.playpad.view.PseudoClasses;
 import de.tobias.playpad.viewcontroller.PadSettingsTabViewController;
 import de.tobias.playpad.viewcontroller.settings.FadeViewController;
@@ -54,12 +54,12 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 			PadSettings padSettings = pad.getPadSettings();
 
 			if (c && !padSettings.isCustomFade())
-				padSettings.setFade(new Fade());
+				padSettings.setFade(new FadeSettings());
 			else if (!c && padSettings.isCustomFade())
 				padSettings.setFade(null);
 
 			if (c)
-				fadeViewController.setFade(padSettings.getFade());
+				fadeViewController.setFadeSettings(padSettings.getFade());
 		});
 
 		warningEnableCheckBox.selectedProperty().addListener((a, b, c) ->
@@ -104,7 +104,7 @@ public class PlayerPadTabViewController extends PadSettingsTabViewController {
 		PadSettings padSettings = pad.getPadSettings();
 
 		if (padSettings.isCustomFade())
-			fadeViewController.setFade(padSettings.getFade());
+			fadeViewController.setFadeSettings(padSettings.getFade());
 
 		customFadeCheckBox.setSelected(padSettings.isCustomFade());
 		if (!padSettings.isCustomFade()) {
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java
index 384bb2ed..87df4b78 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/option/profile/PlayerTabViewController.java
@@ -33,7 +33,7 @@ public class PlayerTabViewController extends ProfileSettingsTabViewController {
 
 		// Player
 		FadeViewController fadeViewController = new FadeViewController();
-		fadeViewController.setFade(Profile.currentProfile().getProfileSettings().getFade());
+		fadeViewController.setFadeSettings(Profile.currentProfile().getProfileSettings().getFade());
 		fadeContainer.getChildren().add(fadeViewController.getParent());
 		setAnchor(fadeViewController.getParent(), 0, 0, 0, 0);
 	}
diff --git a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
index 14515382..2793f426 100644
--- a/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
+++ b/PlayWall/src/main/java/de/tobias/playpad/viewcontroller/settings/FadeViewController.java
@@ -3,7 +3,7 @@ package de.tobias.playpad.viewcontroller.settings;
 import de.thecodelabs.utils.ui.NVC;
 import de.thecodelabs.utils.util.Localization;
 import de.tobias.playpad.Strings;
-import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.FadeSettings;
 import javafx.fxml.FXML;
 import javafx.scene.control.CheckBox;
 import javafx.scene.control.Label;
@@ -29,8 +29,10 @@ public class FadeViewController extends NVC {
 	private CheckBox fadeOutPauseCheckBox;
 	@FXML
 	private CheckBox fadeOutStopCheckBox;
+	@FXML
+	private CheckBox fadeOutEofCheckBox;
 
-	private Fade fade;
+	private FadeSettings fade;
 
 	public FadeViewController() {
 		load("view/settings", "FadeView", Localization.getBundle());
@@ -54,13 +56,14 @@ public class FadeViewController extends NVC {
 			fade.setFadeOut(seconds);
 		});
 
-		fadeInStartCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeInStart(c));
-		fadeInPauseCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeInPause(c));
-		fadeOutPauseCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeOutPause(c));
-		fadeOutStopCheckBox.selectedProperty().addListener((a, b, c) -> fade.setFadeOutStop(c));
+		fadeInStartCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeInStart(newValue));
+		fadeInPauseCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeInPause(newValue));
+		fadeOutPauseCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeOutPause(newValue));
+		fadeOutStopCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeOutStop(newValue));
+		fadeOutEofCheckBox.selectedProperty().addListener((observable, oldValue, newValue) -> fade.setFadeOutEof(newValue));
 	}
 
-	public void setFade(Fade fade) {
+	public void setFadeSettings(FadeSettings fade) {
 		this.fade = fade;
 
 		if (fade != null) {
@@ -76,6 +79,7 @@ public class FadeViewController extends NVC {
 			fadeInPauseCheckBox.setSelected(fade.isFadeInPause());
 			fadeOutPauseCheckBox.setSelected(fade.isFadeOutPause());
 			fadeOutStopCheckBox.setSelected(fade.isFadeOutStop());
+			fadeOutEofCheckBox.setSelected(fade.isFadeOutEof());
 		}
 	}
 }
diff --git a/PlayWall/src/main/resources/lang/ui_de.properties b/PlayWall/src/main/resources/lang/ui_de.properties
index 48792534..fa738571 100755
--- a/PlayWall/src/main/resources/lang/ui_de.properties
+++ b/PlayWall/src/main/resources/lang/ui_de.properties
@@ -69,8 +69,9 @@ settings.player.label.fadeOut=Ausblenden (in s):
 settings.player.label.startIn=... nach Start
 settings.player.label.pauseIn=... bei Pause
 settings.player.label.pauseOut=... bei Pause
-settings.player.label.stopOut=... bei Stop/EoF
-settings.player.label.fadeInfo=Wird beim Ein- oder Ausblenden die Dauer auf 0 gesetzt, so findet keine \u00DCberblendung statt. Wenn die Datei zu Ende ist, findet kein Ausblenden statt.
+settings.player.label.stopOut=... bei Stop
+settings.player.label.eofOut=... bei End of File
+settings.player.label.fadeInfo=Wird beim Ein- oder Ausblenden die Dauer auf 0 gesetzt, so findet keine \u00DCberblendung statt.
 settings.player.label.timeDisplay=Zeitanzeige:
 settings.update.label.current=Installierte Version:
 settings.update.label.search=Nach Updates suchen:
diff --git a/PlayWall/src/main/resources/view/settings/FadeView.fxml b/PlayWall/src/main/resources/view/settings/FadeView.fxml
index 41b62886..94c88e46 100644
--- a/PlayWall/src/main/resources/view/settings/FadeView.fxml
+++ b/PlayWall/src/main/resources/view/settings/FadeView.fxml
@@ -51,6 +51,8 @@
                                           text="%settings.player.label.pauseOut"/>
                                 <CheckBox fx:id="fadeOutStopCheckBox" mnemonicParsing="false"
                                           text="%settings.player.label.stopOut"/>
+                                <CheckBox fx:id="fadeOutEofCheckBox" mnemonicParsing="false"
+                                          text="%settings.player.label.eofOut"/>
                             </children>
                         </HBox>
                     </children>
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java
index f85ef7e4..a935edd4 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettings.java
@@ -7,7 +7,7 @@ import de.tobias.playpad.project.ref.ProjectReference;
 import de.tobias.playpad.server.sync.command.CommandManager;
 import de.tobias.playpad.server.sync.command.Commands;
 import de.tobias.playpad.server.sync.listener.upstream.PadSettingsUpdateListener;
-import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.FadeSettings;
 import de.tobias.playpad.tigger.Trigger;
 import de.tobias.playpad.tigger.TriggerPoint;
 import javafx.beans.binding.BooleanBinding;
@@ -31,7 +31,7 @@ public class PadSettings {
 	private DoubleProperty speedProperty = new SimpleDoubleProperty(1.0);
 	private BooleanProperty loopProperty = new SimpleBooleanProperty(false);
 	private ObjectProperty<TimeMode> timeModeProperty = new SimpleObjectProperty<>();
-	private ObjectProperty<Fade> fadeProperty = new SimpleObjectProperty<>();
+	private ObjectProperty<FadeSettings> fadeProperty = new SimpleObjectProperty<>();
 	private ObjectProperty<Duration> warningProperty = new SimpleObjectProperty<>();
 	private ObjectProperty<Duration> cueInProperty = new SimpleObjectProperty<>();
 
@@ -137,18 +137,18 @@ public class PadSettings {
 	 *
 	 * @return Fade
 	 */
-	public Fade getFade() {
+	public FadeSettings getFade() {
 		if (fadeProperty.isNull().get() && Profile.currentProfile() != null) {
 			return Profile.currentProfile().getProfileSettings().getFade();
 		}
 		return fadeProperty.get();
 	}
 
-	public void setFade(Fade fade) {
+	public void setFade(FadeSettings fade) {
 		this.fadeProperty.set(fade);
 	}
 
-	public ObjectProperty<Fade> fadeProperty() {
+	public ObjectProperty<FadeSettings> fadeProperty() {
 		return fadeProperty;
 	}
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java
index f3fc932c..82e70e61 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/PadSettingsSerializer.java
@@ -4,7 +4,7 @@ import de.thecodelabs.logger.Logger;
 import de.thecodelabs.storage.settings.UserDefaults;
 import de.tobias.playpad.design.modern.model.ModernCartDesign;
 import de.tobias.playpad.design.modern.serializer.ModernCartDesignSerializer;
-import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.FadeSettings;
 import de.tobias.playpad.tigger.Trigger;
 import de.tobias.playpad.tigger.TriggerPoint;
 import javafx.util.Duration;
@@ -51,7 +51,7 @@ public class PadSettingsSerializer {
 		if (settingsElement.element(TIME_MODE_ELEMENT) != null)
 			padSettings.setTimeMode(TimeMode.valueOf(settingsElement.element(TIME_MODE_ELEMENT).getStringValue()));
 		if (settingsElement.element(FADE_ELEMENT) != null)
-			padSettings.setFade(Fade.load(settingsElement.element(FADE_ELEMENT)));
+			padSettings.setFade(FadeSettings.load(settingsElement.element(FADE_ELEMENT)));
 		if (settingsElement.element(WARNING_ELEMENT) != null) {
 			try {
 				Duration duration = Duration.valueOf(settingsElement.element(WARNING_ELEMENT).getStringValue().replace(" ", ""));
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java
index de3828da..086f8ede 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fade.java
@@ -11,10 +11,10 @@ import javafx.util.Duration;
  */
 public class Fade {
 
-	private FadeDelegate fadeDelegate;
-	private Transition currentFadeTransition;
+	private static final double VELOCITY = 1;
 
-	private double velocity = 1;
+	private final FadeDelegate fadeDelegate;
+	private Transition currentFadeTransition;
 
 	public Fade(FadeDelegate fadeDelegate) {
 		this.fadeDelegate = fadeDelegate;
@@ -60,10 +60,10 @@ public class Fade {
 			protected void interpolate(double frac) {
 				double diff = Math.abs(to - from);
 				if (from < to) { // Fade In
-					double fade = fadeInVolumeMultiplier(frac, velocity);
+					double fade = fadeInVolumeMultiplier(frac);
 					fadeDelegate.onFadeLevelChange(from + fade * diff);
 				} else { // Fade Out
-					double fade = fadeOutVolumeMultiplier(frac, velocity);
+					double fade = fadeOutVolumeMultiplier(frac);
 					double newValue = to + fade * diff;
 					fadeDelegate.onFadeLevelChange(newValue);
 				}
@@ -79,12 +79,12 @@ public class Fade {
 		currentFadeTransition.play();
 	}
 
-	private double fadeInVolumeMultiplier(double time, double velocity) {
-		return Math.pow(Math.E, velocity * (time - 1)) * time;
+	private double fadeInVolumeMultiplier(double time) {
+		return Math.pow(Math.E, VELOCITY * (time - 1)) * time;
 	}
 
-	private double fadeOutVolumeMultiplier(double time, double velocity) {
-		return Math.pow(Math.E, -velocity * time) * (1 - time);
+	private double fadeOutVolumeMultiplier(double time) {
+		return Math.pow(Math.E, -VELOCITY * time) * (1 - time);
 	}
 
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java
index a0f5444c..7e343f61 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/Fadeable.java
@@ -7,6 +7,10 @@ public interface Fadeable {
 
 	void fadeIn();
 
+	default void fadeOut() {
+		fadeOut(null);
+	}
+
 	void fadeOut(Runnable runnable);
 
 	boolean isFadeActive();
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java
index d9eee373..b795033f 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/pad/fade/listener/PadFadeDurationListener.java
@@ -9,7 +9,7 @@ import javafx.util.Duration;
 
 public class PadFadeDurationListener implements ChangeListener<Duration> {
 
-	private Pad pad;
+	private final Pad pad;
 
 	public PadFadeDurationListener(Pad pad) {
 		this.pad = pad;
@@ -17,15 +17,17 @@ public class PadFadeDurationListener implements ChangeListener<Duration> {
 
 	@Override
 	public void changed(ObservableValue<? extends Duration> observable, Duration oldValue, Duration newValue) {
-		if (pad.getPadSettings().getFade().isFadeOutStop()) {
+		if (pad.getPadSettings().getFade().isFadeOutEof()) {
 			final Duration fadeDuration = pad.getPadSettings().getFade().getFadeOut();
 
 			if (pad.getContent() instanceof Durationable) {
-				Durationable durationable = (Durationable) pad.getContent();
-				if (durationable.getPosition() != null && durationable.getDuration() != null) {
-					if (durationable.getPosition().add(fadeDuration).greaterThan(durationable.getDuration())) {
-						fadeOut();
-					}
+				final Durationable durationable = (Durationable) pad.getContent();
+
+				final Duration position = durationable.getPosition();
+				final Duration duration = durationable.getDuration();
+
+				if (position != null && duration != null && position.add(fadeDuration).greaterThan(duration)) {
+					fadeOut();
 				}
 			}
 		}
@@ -33,11 +35,10 @@ public class PadFadeDurationListener implements ChangeListener<Duration> {
 
 	private void fadeOut() {
 		if (pad.getContent() instanceof Fadeable) {
-			Fadeable fadeable = (Fadeable) pad.getContent();
+			final Fadeable fadeable = (Fadeable) pad.getContent();
 			if (!fadeable.isFadeActive()) {
-				fadeable.fadeOut(null);
+				fadeable.fadeOut();
 			}
-
 		}
 	}
 }
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java
index a2039d5c..0b20a03f 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/profile/ProfileSettings.java
@@ -8,7 +8,7 @@ import de.tobias.playpad.action.feedback.LightMode;
 import de.tobias.playpad.design.modern.model.ModernGlobalDesign;
 import de.tobias.playpad.design.modern.serializer.ModernGlobalDesignSerializer;
 import de.tobias.playpad.pad.TimeMode;
-import de.tobias.playpad.settings.Fade;
+import de.tobias.playpad.settings.FadeSettings;
 import javafx.beans.property.BooleanProperty;
 import javafx.beans.property.DoubleProperty;
 import javafx.beans.property.SimpleBooleanProperty;
@@ -66,7 +66,7 @@ public class ProfileSettings {
 	private boolean windowAlwaysOnTop = false;
 
 	@Key
-	private Fade fade = new Fade();
+	private FadeSettings fade = new FadeSettings();
 	@Key
 	private TimeMode playerTimeDisplayMode = TimeMode.REST;
 
@@ -115,7 +115,7 @@ public class ProfileSettings {
 		return windowAlwaysOnTop;
 	}
 
-	public Fade getFade() {
+	public FadeSettings getFade() {
 		return fade;
 	}
 
@@ -168,7 +168,7 @@ public class ProfileSettings {
 		this.windowAlwaysOnTop = windowAlwaysOnTop;
 	}
 
-	public void setFade(Fade fade) {
+	public void setFade(FadeSettings fade) {
 		this.fade = fade;
 	}
 
@@ -247,7 +247,7 @@ public class ProfileSettings {
 			}
 
 			if (root.element(FADE_ELEMENT) != null) {
-				Fade fade = Fade.load(root.element(FADE_ELEMENT));
+				FadeSettings fade = FadeSettings.load(root.element(FADE_ELEMENT));
 				profileSettings.setFade(fade);
 			}
 
diff --git a/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java b/PlayWallCore/src/main/java/de/tobias/playpad/settings/FadeSettings.java
similarity index 81%
rename from PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java
rename to PlayWallCore/src/main/java/de/tobias/playpad/settings/FadeSettings.java
index 4b30a96f..f5202e68 100644
--- a/PlayWallCore/src/main/java/de/tobias/playpad/settings/Fade.java
+++ b/PlayWallCore/src/main/java/de/tobias/playpad/settings/FadeSettings.java
@@ -14,7 +14,7 @@ import org.dom4j.Element;
  * @see PadSettings#getFade()
  * @since 6.0.0
  */
-public class Fade {
+public class FadeSettings {
 
 	private Duration fadeIn;
 	private Duration fadeOut;
@@ -23,11 +23,12 @@ public class Fade {
 	private boolean fadeInPause;
 	private boolean fadeOutPause;
 	private boolean fadeOutStop;
+	private boolean fadeOutEof;
 
 	/**
 	 * Erstellt ein neues Fade mit den Default Werten. (Fade Dauer: 0 sec)
 	 */
-	public Fade() {
+	public FadeSettings() {
 		this(Duration.ONE, Duration.ONE);
 	}
 
@@ -37,8 +38,8 @@ public class Fade {
 	 * @param fadeIn  Fade In Dauer
 	 * @param fadeOut Fade Out Dauer
 	 */
-	public Fade(Duration fadeIn, Duration fadeOut) {
-		this(fadeIn, fadeOut, false, true, true, true);
+	public FadeSettings(Duration fadeIn, Duration fadeOut) {
+		this(fadeIn, fadeOut, false, true, true, true, false);
 	}
 
 	/**
@@ -51,13 +52,14 @@ public class Fade {
 	 * @param fadeOutPause Fade vor Pause
 	 * @param fadeOutStop  Fade vor Stop
 	 */
-	public Fade(Duration fadeIn, Duration fadeOut, boolean fadeInStart, boolean fadeInPause, boolean fadeOutPause, boolean fadeOutStop) {
+	public FadeSettings(Duration fadeIn, Duration fadeOut, boolean fadeInStart, boolean fadeInPause, boolean fadeOutPause, boolean fadeOutStop, boolean fadeOutEof) {
 		this.fadeIn = fadeIn;
 		this.fadeOut = fadeOut;
 		this.fadeInStart = fadeInStart;
 		this.fadeInPause = fadeInPause;
 		this.fadeOutPause = fadeOutPause;
 		this.fadeOutStop = fadeOutStop;
+		this.fadeOutEof = fadeOutEof;
 	}
 
 	public Duration getFadeIn() {
@@ -108,6 +110,14 @@ public class Fade {
 		this.fadeOutStop = fadeOutStop;
 	}
 
+	public boolean isFadeOutEof() {
+		return fadeOutEof;
+	}
+
+	public void setFadeOutEof(boolean fadeOutEof) {
+		this.fadeOutEof = fadeOutEof;
+	}
+
 	/*
 	 * Serialize
 	 */
@@ -116,6 +126,7 @@ public class Fade {
 	private static final String FADE_IN = "FadeIn";
 
 	private static final String ON_STOP_ATTR = "onStop";
+	private static final String ON_EOF_ATTR = "onEof";
 	private static final String ON_PAUSE_ATTR = "onPause";
 	private static final String ON_START_ATTR = "onStart";
 
@@ -129,11 +140,12 @@ public class Fade {
 		fadeOutElement.addText(fadeOut.toString());
 		fadeOutElement.addAttribute(ON_PAUSE_ATTR, String.valueOf(fadeOutPause));
 		fadeOutElement.addAttribute(ON_STOP_ATTR, String.valueOf(fadeOutStop));
+		fadeOutElement.addAttribute(ON_EOF_ATTR, String.valueOf(fadeOutEof));
 	}
 
-	public static Fade load(Element container) {
+	public static FadeSettings load(Element container) {
 		try {
-			Fade fade = new Fade();
+			FadeSettings fade = new FadeSettings();
 
 			Element fadeInElement = container.element(FADE_IN);
 			if (fadeInElement.attributeValue(ON_PAUSE_ATTR) != null)
@@ -147,6 +159,8 @@ public class Fade {
 				fade.setFadeOutPause(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_PAUSE_ATTR)));
 			if (fadeOutElement.attributeValue(ON_STOP_ATTR) != null)
 				fade.setFadeOutStop(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_STOP_ATTR)));
+			if (fadeOutElement.attributeValue(ON_EOF_ATTR) != null)
+				fade.setFadeOutEof(Boolean.parseBoolean(fadeOutElement.attributeValue(ON_EOF_ATTR)));
 			fade.setFadeOut(Duration.valueOf(fadeOutElement.getStringValue().replace(" ", "")));
 			return fade;
 		} catch (Exception e) {
-- 
GitLab