diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java b/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java index 2794c16d36..0053c087aa 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/Overlay.java @@ -29,14 +29,16 @@ import bisq.desktop.util.Transitions; import bisq.core.app.BisqEnvironment; import bisq.core.locale.GlobalSettings; +import bisq.core.locale.LanguageUtil; import bisq.core.locale.Res; import bisq.core.user.DontShowAgainLookup; -import bisq.core.locale.LanguageUtil; import bisq.common.Timer; import bisq.common.UserThread; import bisq.common.util.Utilities; +import com.google.common.reflect.TypeToken; + import org.apache.commons.lang3.StringUtils; import de.jensd.fx.fontawesome.AwesomeIcon; @@ -68,8 +70,8 @@ import javafx.scene.transform.Rotate; import javafx.geometry.HPos; import javafx.geometry.Insets; -import javafx.geometry.Pos; import javafx.geometry.NodeOrientation; +import javafx.geometry.Pos; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; @@ -93,7 +95,7 @@ import lombok.Setter; import lombok.extern.slf4j.Slf4j; @Slf4j -public abstract class Overlay { +public abstract class Overlay> { /////////////////////////////////////////////////////////////////////////////////////////// // Enum @@ -185,12 +187,23 @@ public abstract class Overlay { protected int maxChar = 1800; + private T cast() { + //noinspection unchecked + return (T) this; + } + /////////////////////////////////////////////////////////////////////////////////////////// // Public API /////////////////////////////////////////////////////////////////////////////////////////// public Overlay() { + //noinspection UnstableApiUsage + TypeToken typeToken = new TypeToken<>(getClass()) { + }; + if (!typeToken.isSupertypeOf(getClass())) { + throw new RuntimeException("Subclass of Overlay should be castable to T"); + } } public void show(boolean showAgainChecked) { @@ -266,26 +279,22 @@ public abstract class Overlay { public T onClose(Runnable closeHandler) { this.closeHandlerOptional = Optional.of(closeHandler); - //noinspection unchecked - return (T) this; + return cast(); } public T onAction(Runnable actionHandler) { this.actionHandlerOptional = Optional.of(actionHandler); - //noinspection unchecked - return (T) this; + return cast(); } public T onSecondaryAction(Runnable secondaryActionHandlerOptional) { this.secondaryActionHandlerOptional = Optional.of(secondaryActionHandlerOptional); - //noinspection unchecked - return (T) this; + return cast(); } public T headLine(String headLine) { this.headLine = headLine; - //noinspection unchecked - return (T) this; + return cast(); } public T notification(String message) { @@ -294,8 +303,7 @@ public abstract class Overlay { this.headLine = Res.get("popup.headline.notification"); this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } public T instruction(String message) { @@ -304,8 +312,7 @@ public abstract class Overlay { this.headLine = Res.get("popup.headline.instruction"); this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } public T attention(String message) { @@ -314,8 +321,7 @@ public abstract class Overlay { this.headLine = Res.get("popup.headline.attention"); this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } public T backgroundInfo(String message) { @@ -324,8 +330,7 @@ public abstract class Overlay { this.headLine = Res.get("popup.headline.backgroundInfo"); this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } public T feedback(String message) { @@ -334,8 +339,7 @@ public abstract class Overlay { this.headLine = Res.get("popup.headline.feedback"); this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } public T confirmation(String message) { @@ -344,8 +348,7 @@ public abstract class Overlay { this.headLine = Res.get("popup.headline.confirmation"); this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } public T information(String message) { @@ -354,8 +357,7 @@ public abstract class Overlay { this.headLine = Res.get("popup.headline.information"); this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } public T warning(String message) { @@ -365,8 +367,7 @@ public abstract class Overlay { this.headLine = Res.get("popup.headline.warning"); this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } public T error(String message) { @@ -377,136 +378,116 @@ public abstract class Overlay { this.headLine = Res.get("popup.headline.error"); this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } @SuppressWarnings("UnusedReturnValue") public T showReportErrorButtons() { this.showReportErrorButtons = true; - //noinspection unchecked - return (T) this; + return cast(); } public T message(String message) { this.message = message; setTruncatedMessage(); - //noinspection unchecked - return (T) this; + return cast(); } public T closeButtonText(String closeButtonText) { this.closeButtonText = closeButtonText; - //noinspection unchecked - return (T) this; + return cast(); } public T useReportBugButton() { this.closeButtonText = Res.get("shared.reportBug"); this.closeHandlerOptional = Optional.of(() -> GUIUtil.openWebPage("https://bisq.network/source/bisq/issues")); - //noinspection unchecked - return (T) this; + return cast(); } public T useIUnderstandButton() { this.closeButtonText = Res.get("shared.iUnderstand"); - //noinspection unchecked - return (T) this; + return cast(); } public T actionButtonTextWithGoTo(String target) { this.actionButtonText = Res.get("shared.goTo", Res.get(target)); - //noinspection unchecked - return (T) this; + return cast(); } public T secondaryActionButtonTextWithGoTo(String target) { this.secondaryActionButtonText = Res.get("shared.goTo", Res.get(target)); - //noinspection unchecked - return (T) this; + return cast(); } public T closeButtonTextWithGoTo(String target) { this.closeButtonText = Res.get("shared.goTo", Res.get(target)); - //noinspection unchecked - return (T) this; + return cast(); } public T actionButtonText(String actionButtonText) { this.actionButtonText = actionButtonText; - //noinspection unchecked - return (T) this; + return cast(); } public T secondaryActionButtonText(String secondaryActionButtonText) { this.secondaryActionButtonText = secondaryActionButtonText; - //noinspection unchecked - return (T) this; + return cast(); } public T useShutDownButton() { this.actionButtonText = Res.get("shared.shutDown"); this.actionHandlerOptional = Optional.ofNullable(BisqApp.getShutDownHandler()); - //noinspection unchecked - return (T) this; + return cast(); } public T buttonAlignment(HPos pos) { this.buttonAlignment = pos; - return (T) this; + return cast(); } public T width(double width) { this.width = width; - //noinspection unchecked - return (T) this; + return cast(); } public T maxMessageLength(int maxChar) { this.maxChar = maxChar; - return (T) this; + return cast(); } public T showBusyAnimation() { this.showBusyAnimation = true; - //noinspection unchecked - return (T) this; + return cast(); } public T dontShowAgainId(String key) { this.dontShowAgainId = key; - //noinspection unchecked - return (T) this; + return cast(); } public T dontShowAgainText(String dontShowAgainText) { this.dontShowAgainText = dontShowAgainText; - //noinspection unchecked - return (T) this; + return cast(); } public T hideCloseButton() { this.hideCloseButton = true; - //noinspection unchecked - return (T) this; + return cast(); } public T useAnimation(boolean useAnimation) { this.useAnimation = useAnimation; - //noinspection unchecked - return (T) this; + return cast(); } public T setHeadlineStyle(String headlineStyle) { this.headlineStyle = headlineStyle; - //noinspection unchecked - return (T) this; + return cast(); } public T disableActionButton() { this.disableActionButton = true; - //noinspection unchecked - return (T) this; + return cast(); } diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/TabbedOverlay.java b/desktop/src/main/java/bisq/desktop/main/overlays/TabbedOverlay.java index 8dc484cfa6..94783de4b9 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/TabbedOverlay.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/TabbedOverlay.java @@ -4,7 +4,7 @@ import com.jfoenix.controls.JFXTabPane; import javafx.scene.layout.Region; -public abstract class TabbedOverlay extends Overlay { +public abstract class TabbedOverlay> extends Overlay { protected JFXTabPane tabPane; diff --git a/desktop/src/main/java/bisq/desktop/main/overlays/popups/Popup.java b/desktop/src/main/java/bisq/desktop/main/overlays/popups/Popup.java index 44b7b3518f..3d64c001ae 100644 --- a/desktop/src/main/java/bisq/desktop/main/overlays/popups/Popup.java +++ b/desktop/src/main/java/bisq/desktop/main/overlays/popups/Popup.java @@ -22,7 +22,8 @@ import bisq.desktop.main.overlays.Overlay; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -public class Popup extends Overlay { +// TODO: Type parameter is unused - remove: +public class Popup extends Overlay> { protected final Logger log = LoggerFactory.getLogger(this.getClass()); public Popup() { @@ -41,6 +42,4 @@ public class Popup extends Overlay { protected void onHidden() { PopupManager.onHidden(this); } - - } diff --git a/desktop/src/test/java/bisq/desktop/main/overlays/OverlayTest.java b/desktop/src/test/java/bisq/desktop/main/overlays/OverlayTest.java new file mode 100644 index 0000000000..5ee453bc0e --- /dev/null +++ b/desktop/src/test/java/bisq/desktop/main/overlays/OverlayTest.java @@ -0,0 +1,47 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.desktop.main.overlays; + +import org.junit.Test; + +public class OverlayTest { + + @Test + public void typeSafeCreation() { + new A(); + new C(); + new D<>(); + } + + @Test(expected = RuntimeException.class) + public void typeUnsafeCreation() { + new B(); + } + + private static class A extends Overlay { + } + + private static class B extends Overlay { + } + + private static class C extends TabbedOverlay { + } + + private static class D extends Overlay> { + } +}