-treeShowing = TreeShowing.treeShowing(node);
-treeShowing.addListener((p,o,showing) -> {
- if(showing) {
- myTimeline.start();
- } else {
- myTimeline.stop();
- }
-});
-if(treeShowing.get()) {
- myTimeline.start();
-}
-```
-
-## Freeze Detector
-This library allows you to track whether the JavaFX Application Thread is frozen for a given time.
-This can be useful for debugging purposes, detecting deadlocks or other optimize performance.
-
-#### Maven configuration
-```xml
-
-
- one.jpro.platform
- freeze-detector
- 0.4.4-SNAPSHOT
-
-
-```
-
-#### Gradle configuration
-```groovy
-dependencies {
- implementation 'one.jpro.platform:freeze-detector:0.4.4-SNAPSHOT'
-}
-```
-
## Launch the examples
To run the examples, you can use the following commands:
diff --git a/build.gradle b/build.gradle
index 53ccc40c..ddf9005d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -47,6 +47,9 @@ configure(subprojects.findAll { it.name != 'example' }) {
testImplementation "org.junit.jupiter:junit-jupiter-engine:$JUNIT_VERSION"
testImplementation "one.jpro:jmemorybuddy:$JMEMORYBUDDY_VERSION"
+ testImplementation "one.jpro.platform.jpms:testfx-junit5:$TESTFX_VERSION"
+ testImplementation "one.jpro.platform.jpms:testfx-core:$TESTFX_VERSION"
+ testImplementation "one.jpro.platform.jpms:openjfx-monocle:$MONOCLE_VERSION"
testImplementation "org.mockito:mockito-core:$MOCKITO_VERSION"
testImplementation "org.mockito:mockito-junit-jupiter:$MOCKITO_VERSION"
testImplementation "org.hamcrest:hamcrest:$HAMCREST_VERSION"
@@ -79,12 +82,11 @@ configure(subprojects.findAll { it.name != 'example' }) {
}
}
-configure([project("tree-showing"), project("jpro-auth:core"), project("jpro-auth:routing"), project("jpro-file"),
+configure([project("jpro-auth:core"), project("jpro-auth:routing"), project("jpro-file"),
project("jpro-image-manager"), project("jpro-mail"), project("jpro-mdfx"), project("jpro-media"),
- project("jpro-scenegraph"), project("jpro-session"), project("jpro-sipjs"),
- project("jpro-html-scrollpane"), project("freeze-detector"), project("jpro-routing:core"),
- project("jpro-routing:dev"), project("jpro-routing:popup"), project("jpro-webrtc"), project("jpro-youtube"),
- project("internal:openlink"), project("internal:util")]) {
+ project("jpro-scenegraph"), project("jpro-session"), project("jpro-sipjs"), project("jpro-utils"),
+ project("jpro-html-scrollpane"), project("jpro-routing:core"), project("jpro-routing:dev"),
+ project("jpro-routing:popup"), project("jpro-webrtc"), project("jpro-youtube")]) {
apply plugin: 'maven-publish'
apply plugin: 'signing'
apply plugin: 'tech.yanand.maven-central-publish'
@@ -96,13 +98,7 @@ configure([project("tree-showing"), project("jpro-auth:core"), project("jpro-aut
publications {
mavenJava(MavenPublication) {
groupId = 'one.jpro.platform'
-
- if (project.path.startsWith(":internal")) {
- artifactId = "jpro-${isParentASubproject ? "${project.parent.name}-${project.name}" : "${project.name}"}"
- } else {
- artifactId = isParentASubproject ? "${project.parent.name}-${project.name}" : "${project.name}"
- }
-
+ artifactId = isParentASubproject ? "${project.parent.name}-${project.name}" : "${project.name}"
version = JPRO_PLATFORM_VERSION
// Ensure only one component is included in the publication
diff --git a/freeze-detector/src/main/java/module-info.java b/freeze-detector/src/main/java/module-info.java
deleted file mode 100644
index ccf5e023..00000000
--- a/freeze-detector/src/main/java/module-info.java
+++ /dev/null
@@ -1,10 +0,0 @@
-/**
- * Freeze detector module descriptor.
- *
- * @author Besmir Beqiri
- */
-module one.jpro.platform.freezedetector {
- requires javafx.graphics;
-
- exports one.jpro.platform.freezedetector;
-}
\ No newline at end of file
diff --git a/freeze-detector/src/test/java/module-info.java b/freeze-detector/src/test/java/module-info.java
deleted file mode 100644
index 83696850..00000000
--- a/freeze-detector/src/test/java/module-info.java
+++ /dev/null
@@ -1,16 +0,0 @@
-/**
- * Module descriptor for the JPro Platform Freeze Detector Test module.
- *
- * @author Besmir Beqiri
- */
-module one.jpro.platform.freezedetector.test {
- requires one.jpro.platform.freezedetector;
- requires org.slf4j;
-
- requires org.junit.jupiter;
- requires org.testfx.core;
- requires org.testfx.junit5;
- requires org.assertj.core;
-
- opens one.jpro.platform.freezedetector.test;
-}
\ No newline at end of file
diff --git a/internal/openlink/build.gradle b/internal/openlink/build.gradle
deleted file mode 100644
index 17be7fcb..00000000
--- a/internal/openlink/build.gradle
+++ /dev/null
@@ -1,25 +0,0 @@
-java {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
-}
-
-dependencies {
- implementation project(":internal:util")
- implementation "org.jetbrains:annotations:$JETBRAINS_ANNOTATIONS_VERSION"
- implementation "org.slf4j:slf4j-api:$SLF4J_API_VERSION"
-
- testImplementation("org.mockito:mockito-core:$MOCKITO_VERSION")
- testImplementation("org.mockito:mockito-junit-jupiter:$MOCKITO_VERSION")
- testRuntimeOnly "ch.qos.logback:logback-classic:$LOGBACK_VERSION"
-}
-
-publishing {
- publications {
- mavenJava(MavenPublication) {
- pom {
- name = 'JPro Open Link'
- description = 'A module that helps launching the default browser of the running platform.'
- }
- }
- }
-}
\ No newline at end of file
diff --git a/internal/openlink/src/main/java/module-info.java b/internal/openlink/src/main/java/module-info.java
deleted file mode 100644
index 256ec5bd..00000000
--- a/internal/openlink/src/main/java/module-info.java
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * The module descriptor for the OpenLink module.
- *
- * @author Besmir Beqiri
- */
-module one.jpro.platform.internal.openlink {
- requires javafx.controls;
- requires org.jetbrains.annotations;
- requires org.slf4j;
-
- requires one.jpro.platform.internal.util;
-
- exports one.jpro.platform.internal.openlink;
-}
\ No newline at end of file
diff --git a/internal/openlink/src/test/java/one/jpro/platform/internal/openlink/test/OpenLinkTests.java b/internal/openlink/src/test/java/one/jpro/platform/internal/openlink/test/OpenLinkTests.java
deleted file mode 100644
index 1ff48b29..00000000
--- a/internal/openlink/src/test/java/one/jpro/platform/internal/openlink/test/OpenLinkTests.java
+++ /dev/null
@@ -1,68 +0,0 @@
-package one.jpro.platform.internal.openlink.test;
-
-import one.jpro.platform.internal.openlink.OpenLink;
-import one.jpro.platform.internal.util.PlatformUtils;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.mockito.Mock;
-
-import java.io.IOException;
-import java.net.URI;
-
-import static org.mockito.Mockito.*;
-
-/**
- * OpenLink tests.
- *
- * @author Besmir Beqiri
- */
-public class OpenLinkTests {
-
- @Mock
- private static Runtime runtime;
-
- @BeforeAll
- public static void setUp() {
- mockStatic(Runtime.class);
- mockStatic(PlatformUtils.class);
-
- runtime = mock(Runtime.class);
- when(Runtime.getRuntime()).thenReturn(runtime);
- }
-
- @Test
- public void testOpenURLOnMac() throws IOException {
- when(PlatformUtils.isDesktop()).thenReturn(true);
- when(PlatformUtils.isMac()).thenReturn(true);
- when(PlatformUtils.isWindows()).thenReturn(false);
- when(PlatformUtils.isLinux()).thenReturn(false);
-
- OpenLink.openURL(URI.create("http://www.example.com").toURL());
-
- verify(runtime).exec(new String[] {"open", "http://www.example.com"});
- }
-
- @Test
- public void testOpenURLOnWindows() throws IOException {
- when(PlatformUtils.isDesktop()).thenReturn(true);
- when(PlatformUtils.isMac()).thenReturn(false);
- when(PlatformUtils.isWindows()).thenReturn(true);
- when(PlatformUtils.isLinux()).thenReturn(false);
-
- OpenLink.openURL(URI.create("http://www.example.com").toURL());
-
- verify(runtime).exec(new String[] {"rundll32","url.dll,FileProtocolHandler", "http://www.example.com"});
- }
-
- @Test
- public void testOpenURLOnLinux() throws IOException {
- when(PlatformUtils.isDesktop()).thenReturn(true);
- when(PlatformUtils.isMac()).thenReturn(false);
- when(PlatformUtils.isWindows()).thenReturn(false);
- when(PlatformUtils.isLinux()).thenReturn(true);
-
- OpenLink.openURL(URI.create("http://www.example.com").toURL());
-
- verify(runtime).exec(new String[] {"xdg-open", "http://www.example.com"});
- }
-}
diff --git a/internal/util/build.gradle b/internal/util/build.gradle
deleted file mode 100644
index a9154196..00000000
--- a/internal/util/build.gradle
+++ /dev/null
@@ -1,23 +0,0 @@
-java {
- sourceCompatibility = JavaVersion.VERSION_11
- targetCompatibility = JavaVersion.VERSION_11
-}
-
-dependencies {
- implementation "org.jetbrains:annotations:$JETBRAINS_ANNOTATIONS_VERSION"
- implementation "org.slf4j:slf4j-api:$SLF4J_API_VERSION"
-
- testImplementation "org.assertj:assertj-core:$ASSERTJ_VERSION"
- testRuntimeOnly "ch.qos.logback:logback-classic:$LOGBACK_VERSION"
-}
-
-publishing {
- publications {
- mavenJava(MavenPublication) {
- pom {
- name = 'JPro Utils'
- description = 'A utility module offering essential tools for process management and platform-specific functionalities'
- }
- }
- }
-}
diff --git a/internal/util/src/main/java/module-info.java b/internal/util/src/main/java/module-info.java
deleted file mode 100644
index 6901ba00..00000000
--- a/internal/util/src/main/java/module-info.java
+++ /dev/null
@@ -1,11 +0,0 @@
-/**
- * The module descriptor for the internal Process module.
- *
- * @author Besmir Beqiri
- */
-module one.jpro.platform.internal.util {
- requires org.jetbrains.annotations;
- requires org.slf4j;
-
- exports one.jpro.platform.internal.util;
-}
\ No newline at end of file
diff --git a/jpro-auth/core/build.gradle b/jpro-auth/core/build.gradle
index 1e35b6c5..53f54bb6 100755
--- a/jpro-auth/core/build.gradle
+++ b/jpro-auth/core/build.gradle
@@ -3,7 +3,7 @@ plugins {
}
dependencies {
- implementation project(":internal:openlink")
+ api project(":jpro-utils")
implementation "com.sandec.jpro:jpro-webapi:$JPRO_VERSION"
implementation "com.auth0:java-jwt:$AUTH0_JAVAJWT_VERSION"
implementation "one.jpro.platform.jpms:jwks-rsa:$AUTH0_JWKSRSA_VERSION"
diff --git a/jpro-auth/core/src/main/java/module-info.java b/jpro-auth/core/src/main/java/module-info.java
index 5a3a6498..39ad825b 100644
--- a/jpro-auth/core/src/main/java/module-info.java
+++ b/jpro-auth/core/src/main/java/module-info.java
@@ -8,13 +8,13 @@
requires transitive javafx.controls;
requires transitive org.json;
requires transitive org.slf4j;
+ requires transitive one.jpro.platform.utils;
requires org.jetbrains.annotations;
requires java.net.http;
requires jpro.webapi;
requires jwks.rsa;
requires com.auth0.jwt;
- requires one.jpro.platform.internal.openlink;
opens one.jpro.platform.auth.core;
opens one.jpro.platform.auth.core.authentication;
diff --git a/jpro-auth/core/src/main/java/one/jpro/platform/auth/core/http/impl/HttpServerImpl.java b/jpro-auth/core/src/main/java/one/jpro/platform/auth/core/http/impl/HttpServerImpl.java
index b90485f7..aae04178 100644
--- a/jpro-auth/core/src/main/java/one/jpro/platform/auth/core/http/impl/HttpServerImpl.java
+++ b/jpro-auth/core/src/main/java/one/jpro/platform/auth/core/http/impl/HttpServerImpl.java
@@ -6,7 +6,7 @@
import one.jpro.platform.auth.core.http.HttpServer;
import one.jpro.platform.auth.core.http.HttpServerException;
import one.jpro.platform.auth.core.http.HttpStatus;
-import one.jpro.platform.internal.openlink.OpenLink;
+import one.jpro.platform.utils.OpenLink;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
diff --git a/jpro-html-scrollpane/build.gradle b/jpro-html-scrollpane/build.gradle
index 1613301e..b1959d30 100644
--- a/jpro-html-scrollpane/build.gradle
+++ b/jpro-html-scrollpane/build.gradle
@@ -1,5 +1,5 @@
dependencies {
- implementation project(":tree-showing")
+ api project(":jpro-utils")
implementation "com.sandec.jpro:jpro-webapi:$JPRO_VERSION"
implementation "one.jpro:jmemorybuddy:$JMEMORYBUDDY_VERSION"
implementation "org.slf4j:slf4j-api:$SLF4J_API_VERSION"
@@ -9,10 +9,8 @@ publishing {
publications {
mavenJava(MavenPublication) {
pom {
- name = 'JPro Auth Core'
- description = 'A module for adding advanced authentication and authorization to JPro/JavaFX ' +
- 'applications, supporting OAuth 2.0, OpenID Connect, integration with multiple identity ' +
- 'providers and asynchronous operations for enhanced performance.'
+ name = 'JPro HTML Scrollpane Skin'
+ description = 'A module containing a ScrollPane skin for HTML content'
}
}
}
diff --git a/jpro-html-scrollpane/src/main/java/module-info.java b/jpro-html-scrollpane/src/main/java/module-info.java
index ad4b994b..c6064ddc 100644
--- a/jpro-html-scrollpane/src/main/java/module-info.java
+++ b/jpro-html-scrollpane/src/main/java/module-info.java
@@ -1,8 +1,7 @@
module one.jpro.platform.htmlscrollpane {
- requires javafx.controls;
+ requires transitive one.jpro.platform.utils;
requires jpro.webapi;
requires one.jpro.jmemorybuddy;
- requires one.jpro.platform.treeshowing;
requires org.slf4j;
exports one.jpro.platform.htmlscrollpane;
diff --git a/jpro-html-scrollpane/src/main/java/one/jpro/platform/htmlscrollpane/HTMLScrollPaneSkin.java b/jpro-html-scrollpane/src/main/java/one/jpro/platform/htmlscrollpane/HTMLScrollPaneSkin.java
index b37330b4..5bb95a69 100644
--- a/jpro-html-scrollpane/src/main/java/one/jpro/platform/htmlscrollpane/HTMLScrollPaneSkin.java
+++ b/jpro-html-scrollpane/src/main/java/one/jpro/platform/htmlscrollpane/HTMLScrollPaneSkin.java
@@ -16,7 +16,7 @@
import javafx.scene.layout.StackPane;
import javafx.stage.PopupWindow;
import javafx.stage.Window;
-import one.jpro.platform.treeshowing.TreeShowing;
+import one.jpro.platform.utils.TreeShowing;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -25,6 +25,74 @@
import java.util.List;
import java.util.Random;
+/**
+ * The {@code HTMLScrollPaneSkin} class provides a custom skin for the JavaFX {@link ScrollPane}
+ * control, enabling the integration of HTML content within the scroll pane. This skin leverages
+ * the {@link HTMLView} component to render HTML content and manages resource cleanup to prevent
+ * memory leaks by monitoring the visibility of the associated {@code ScrollPane} using the
+ * {@link TreeShowing} utility.
+ *
+ *
+ * In JavaFX applications, embedding HTML content within UI components like {@code ScrollPane}
+ * can lead to resource retention issues if animations or background tasks continue running
+ * after the node is no longer visible. The {@code HTMLScrollPaneSkin} addresses this by:
+ *
+ *
+ *
+ * - Embedding an {@code HTMLView} within the scroll pane to display HTML content.
+ * - Monitoring the {@code ScrollPane}'s visibility using {@code TreeShowing} to manage
+ * animations and background tasks effectively.
+ * - Implementing workarounds for internal JavaFX behaviors to ensure proper resource cleanup.
+ *
+ *
+ *
+ * By using {@code HTMLScrollPaneSkin}, developers can seamlessly integrate HTML content into
+ * scrollable regions of their JavaFX applications while maintaining optimal memory and resource
+ * management.
+ *
+ *
+ *
+ * Example Usage:
+ *
+ *
+ * {@code
+ * import javafx.application.Application;
+ * import javafx.scene.Scene;
+ * import javafx.scene.control.ScrollPane;
+ * import javafx.stage.Stage;
+ *
+ * public class HTMLScrollPaneExample extends Application {
+ * @Override
+ * public void start(Stage primaryStage) {
+ * ScrollPane scrollPane = new ScrollPane();
+ *
+ * // Apply the custom HTMLScrollPaneSkin
+ * scrollPane.setSkin(new HTMLScrollPaneSkin(scrollPane, "additional-attributes"));
+ *
+ * Scene scene = new Scene(scrollPane, 800, 600);
+ * primaryStage.setScene(scene);
+ * primaryStage.setTitle("HTMLScrollPaneSkin Example");
+ * primaryStage.show();
+ * }
+ *
+ * public static void main(String[] args) {
+ * launch(args);
+ * }
+ * }
+ * }
+ *
+ *
+ * In this example, a {@code ScrollPane} is created and assigned the {@code HTMLScrollPaneSkin}
+ * with additional attributes. The skin manages the embedding of HTML content and ensures that
+ * resources are properly cleaned up when the scroll pane is no longer part of the scene graph.
+ *
+ *
+ * @see ScrollPane
+ * @see HTMLView
+ * @see TreeShowing
+ *
+ * @author Florian Kirmaier
+ */
public class HTMLScrollPaneSkin extends SkinBase {
private static final Logger logger = LoggerFactory.getLogger(HTMLScrollPaneSkin.class);
diff --git a/jpro-routing/build.gradle b/jpro-routing/build.gradle
index 12e59ef4..cce56d9d 100644
--- a/jpro-routing/build.gradle
+++ b/jpro-routing/build.gradle
@@ -34,8 +34,8 @@ configure([project(':jpro-routing:core'), project(':jpro-routing:dev'), project(
configure([project(':jpro-routing:core')]) {
dependencies {
+ api project(":jpro-utils")
api "SANDEC:simplefx_2.12:$SIMPLEFX_VERSION"
- api project(":internal:openlink")
}
publishing {
diff --git a/jpro-routing/core/src/main/java/module-info.java b/jpro-routing/core/src/main/java/module-info.java
index 39b293c0..07a1786b 100644
--- a/jpro-routing/core/src/main/java/module-info.java
+++ b/jpro-routing/core/src/main/java/module-info.java
@@ -4,13 +4,13 @@
requires transitive de.sandec.jnodes;
requires transitive one.jpro.jmemorybuddy;
+ requires transitive one.jpro.platform.utils;
requires transitive jpro.webapi;
requires transitive simplefx.core;
requires transitive simplefx.utility;
requires transitive simplefx.wrapping;
requires transitive simplefx.extended;
requires transitive scala.library;
- requires transitive one.jpro.platform.internal.openlink;
exports one.jpro.platform.routing;
exports one.jpro.platform.routing.crawl;
diff --git a/jpro-routing/core/src/main/scala/one/jpro/platform/routing/LinkUtil.scala b/jpro-routing/core/src/main/scala/one/jpro/platform/routing/LinkUtil.scala
index 2d4b65a9..1dc7c7a8 100644
--- a/jpro-routing/core/src/main/scala/one/jpro/platform/routing/LinkUtil.scala
+++ b/jpro-routing/core/src/main/scala/one/jpro/platform/routing/LinkUtil.scala
@@ -12,7 +12,7 @@ import org.slf4j.{Logger, LoggerFactory}
object LinkUtil {
private var openLinkExternalFun: String => Unit = { link =>
- import one.jpro.platform.internal.openlink.OpenLink
+ import one.jpro.platform.utils.OpenLink
OpenLink.openURL(link)
}
def setOpenLinkExternalFun(x: String => Unit): Unit = {
diff --git a/jpro-routing/core/src/main/scala/one/jpro/platform/routing/sessionmanager/SessionManager.scala b/jpro-routing/core/src/main/scala/one/jpro/platform/routing/sessionmanager/SessionManager.scala
index 324d0958..b3a9803e 100644
--- a/jpro-routing/core/src/main/scala/one/jpro/platform/routing/sessionmanager/SessionManager.scala
+++ b/jpro-routing/core/src/main/scala/one/jpro/platform/routing/sessionmanager/SessionManager.scala
@@ -9,7 +9,7 @@ import org.slf4j.{Logger, LoggerFactory}
import simplefx.all._
import simplefx.core._
import simplefx.experimental._
-import one.jpro.platform.internal.openlink.OpenLink
+import one.jpro.platform.utils.OpenLink
import java.net.URI
import java.util.function.Consumer
diff --git a/freeze-detector/build.gradle b/jpro-utils/build.gradle
similarity index 57%
rename from freeze-detector/build.gradle
rename to jpro-utils/build.gradle
index 6145b4e0..12c1c96d 100644
--- a/freeze-detector/build.gradle
+++ b/jpro-utils/build.gradle
@@ -1,9 +1,13 @@
+java {
+ sourceCompatibility = JavaVersion.VERSION_11
+ targetCompatibility = JavaVersion.VERSION_11
+}
+
dependencies {
- api "org.slf4j:slf4j-api:$SLF4J_API_VERSION"
+ implementation "org.jetbrains:annotations:$JETBRAINS_ANNOTATIONS_VERSION"
+ implementation "org.slf4j:slf4j-api:$SLF4J_API_VERSION"
- testImplementation "one.jpro.platform.jpms:testfx-junit5:$TESTFX_VERSION"
- testImplementation "one.jpro.platform.jpms:testfx-core:$TESTFX_VERSION"
- testImplementation "one.jpro.platform.jpms:openjfx-monocle:$MONOCLE_VERSION"
+ testImplementation "one.jpro:jmemorybuddy:$JMEMORYBUDDY_VERSION"
}
test {
@@ -22,9 +26,9 @@ publishing {
publications {
mavenJava(MavenPublication) {
pom {
- name = 'Freeze Detector'
- description = 'A module that allows you to track whether the JavaFX Application Thread is frozen for ' +
- 'a given time, useful for debugging purposes, detecting deadlocks, or optimizing performance.'
+ name = 'JPro Utils'
+ description = 'A utility module offering essential tools for various functionalities to enhance the ' +
+ 'development of **JPro/JavaFX** applications'
}
}
}
diff --git a/jpro-utils/src/main/java/module-info.java b/jpro-utils/src/main/java/module-info.java
new file mode 100644
index 00000000..6a0e55ab
--- /dev/null
+++ b/jpro-utils/src/main/java/module-info.java
@@ -0,0 +1,12 @@
+/**
+ * The module descriptor for the JPro Utils module.
+ *
+ * @author Besmir Beqiri
+ */
+module one.jpro.platform.utils {
+ requires transitive javafx.controls;
+ requires org.jetbrains.annotations;
+ requires org.slf4j;
+
+ exports one.jpro.platform.utils;
+}
\ No newline at end of file
diff --git a/internal/util/src/main/java/one/jpro/platform/internal/util/CommandRunner.java b/jpro-utils/src/main/java/one/jpro/platform/utils/CommandRunner.java
similarity index 99%
rename from internal/util/src/main/java/one/jpro/platform/internal/util/CommandRunner.java
rename to jpro-utils/src/main/java/one/jpro/platform/utils/CommandRunner.java
index d8a94155..598c762e 100644
--- a/internal/util/src/main/java/one/jpro/platform/internal/util/CommandRunner.java
+++ b/jpro-utils/src/main/java/one/jpro/platform/utils/CommandRunner.java
@@ -1,4 +1,4 @@
-package one.jpro.platform.internal.util;
+package one.jpro.platform.utils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
diff --git a/freeze-detector/src/main/java/one/jpro/platform/freezedetector/FreezeDetector.java b/jpro-utils/src/main/java/one/jpro/platform/utils/FreezeDetector.java
similarity index 89%
rename from freeze-detector/src/main/java/one/jpro/platform/freezedetector/FreezeDetector.java
rename to jpro-utils/src/main/java/one/jpro/platform/utils/FreezeDetector.java
index 9610e125..d5a15b04 100644
--- a/freeze-detector/src/main/java/one/jpro/platform/freezedetector/FreezeDetector.java
+++ b/jpro-utils/src/main/java/one/jpro/platform/utils/FreezeDetector.java
@@ -1,4 +1,4 @@
-package one.jpro.platform.freezedetector;
+package one.jpro.platform.utils;
import javafx.animation.AnimationTimer;
import javafx.application.Platform;
@@ -6,6 +6,12 @@
import java.time.Duration;
import java.util.function.BiConsumer;
+/**
+ * This class allows you to track whether the JavaFX Application Thread is frozen for a given time.
+ * This can be useful for debugging purposes, detecting deadlocks or other optimize performance.
+ *
+ * @author Florian Kirmaier
+ */
public class FreezeDetector {
Thread fxthread;
diff --git a/internal/openlink/src/main/java/one/jpro/platform/internal/openlink/OpenLink.java b/jpro-utils/src/main/java/one/jpro/platform/utils/OpenLink.java
similarity index 94%
rename from internal/openlink/src/main/java/one/jpro/platform/internal/openlink/OpenLink.java
rename to jpro-utils/src/main/java/one/jpro/platform/utils/OpenLink.java
index 07cce160..1a8cba1c 100644
--- a/internal/openlink/src/main/java/one/jpro/platform/internal/openlink/OpenLink.java
+++ b/jpro-utils/src/main/java/one/jpro/platform/utils/OpenLink.java
@@ -1,6 +1,5 @@
-package one.jpro.platform.internal.openlink;
+package one.jpro.platform.utils;
-import one.jpro.platform.internal.util.PlatformUtils;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
diff --git a/internal/util/src/main/java/one/jpro/platform/internal/util/PlatformUtils.java b/jpro-utils/src/main/java/one/jpro/platform/utils/PlatformUtils.java
similarity index 98%
rename from internal/util/src/main/java/one/jpro/platform/internal/util/PlatformUtils.java
rename to jpro-utils/src/main/java/one/jpro/platform/utils/PlatformUtils.java
index e62989cf..ef299fed 100644
--- a/internal/util/src/main/java/one/jpro/platform/internal/util/PlatformUtils.java
+++ b/jpro-utils/src/main/java/one/jpro/platform/utils/PlatformUtils.java
@@ -1,4 +1,4 @@
-package one.jpro.platform.internal.util;
+package one.jpro.platform.utils;
/**
* Platform utilities.
diff --git a/tree-showing/src/main/java/one/jpro/platform/treeshowing/TreeShowing.java b/jpro-utils/src/main/java/one/jpro/platform/utils/TreeShowing.java
similarity index 52%
rename from tree-showing/src/main/java/one/jpro/platform/treeshowing/TreeShowing.java
rename to jpro-utils/src/main/java/one/jpro/platform/utils/TreeShowing.java
index e5543b89..a1b155d5 100644
--- a/tree-showing/src/main/java/one/jpro/platform/treeshowing/TreeShowing.java
+++ b/jpro-utils/src/main/java/one/jpro/platform/utils/TreeShowing.java
@@ -1,4 +1,4 @@
-package one.jpro.platform.treeshowing;
+package one.jpro.platform.utils;
import javafx.beans.property.BooleanProperty;
import javafx.beans.property.SimpleBooleanProperty;
@@ -7,6 +7,78 @@
import javafx.scene.Scene;
import javafx.stage.Window;
+/**
+ * The {@code TreeShowing} class provides access to the internal {@code "treeShowing"} property of
+ * JavaFX {@link javafx.scene.Node Nodes}. This property is essential for determining whether a
+ * {@code Node} is currently part of the scene graph and actively being displayed.
+ *
+ *
+ * In JavaFX, a {@code Node} eligible for garbage collection might still be retained in memory
+ * due to ongoing animations or background tasks. The internal {@code "treeShowing"} property
+ * tracks the visibility and usage of each {@code Node}, but it is not exposed through the standard
+ * JavaFX API. The {@code TreeShowing} class bridges this gap, enabling developers to monitor
+ * a node's lifecycle and manage resources effectively to prevent memory leaks.
+ *
+ *
+ *
+ * By utilizing the {@code TreeShowing} class, developers can:
+ *
+ *
+ *
+ * - Detect when a {@code Node} is removed from the scene graph.
+ * - Stop associated animations or background tasks to free up resources.
+ *
+ *
+ *
+ * This facilitates the creation of robust, memory-efficient JavaFX applications by ensuring that
+ * unused nodes do not retain unnecessary resources.
+ *
+ *
+ *
+ * Example Usage:
+ *
+ *
+ * {@code
+ * import javafx.animation.Timeline;
+ * import javafx.scene.Node;
+ *
+ * public class Example {
+ * public void setupNode(Node myNode) {
+ * // Create a Timeline animation
+ * Timeline myTimeline = new Timeline();
+ * myTimeline.setCycleCount(Timeline.INDEFINITE);
+ *
+ * // Obtain the TreeShowing instance for the node
+ * TreeShowing treeShowing = TreeShowing.treeShowing(myNode);
+ *
+ * // Add a listener to respond to changes in the treeShowing property
+ * treeShowing.addListener((observable, oldValue, showing) -> {
+ * if (showing) {
+ * // Start the animation when the node is part of the scene graph
+ * myTimeline.play();
+ * } else {
+ * // Stop the animation when the node is removed from the scene graph
+ * myTimeline.stop();
+ * }
+ * });
+ *
+ * // Immediately start the animation if the node is already showing
+ * if (treeShowing.get()) {
+ * myTimeline.play();
+ * }
+ * }
+ * }
+ * }
+ *
+ *
+ * In this example, the listener monitors the {@code "treeShowing"} property of {@code myNode}.
+ * When {@code myNode} is added to the scene graph, the animation starts. Conversely, when
+ * {@code myNode} is removed, the animation stops, ensuring that resources are managed
+ * efficiently.
+ *
+ *
+ * @author Florian Kirmaier
+ */
public class TreeShowing {
private static final Object KEY_TREE_SHOWING = new Object();
diff --git a/jpro-utils/src/test/java/module-info.java b/jpro-utils/src/test/java/module-info.java
new file mode 100644
index 00000000..3e8a6ef6
--- /dev/null
+++ b/jpro-utils/src/test/java/module-info.java
@@ -0,0 +1,21 @@
+/**
+ * Module descriptor for the JPro Utils Test module.
+ *
+ * @author Besmir Beqiri
+ */
+module one.jpro.platform.utils.test {
+ requires one.jpro.platform.utils;
+ requires one.jpro.jmemorybuddy;
+ requires org.slf4j;
+
+ requires org.junit.jupiter;
+ requires org.testfx.core;
+ requires org.testfx.junit5;
+ requires org.assertj.core;
+ requires org.mockito;
+ requires org.mockito.junit.jupiter;
+ requires jdk.attach; // Required by Mockito, for Java 21 and later seems to not be required anymore since transitive
+
+ exports one.jpro.platform.utils.test;
+ opens one.jpro.platform.utils.test;
+}
\ No newline at end of file
diff --git a/internal/util/src/test/java/one/jpro/platform/internal/util/CommandRunnerTests.java b/jpro-utils/src/test/java/one/jpro/platform/utils/test/CommandRunnerTests.java
similarity index 97%
rename from internal/util/src/test/java/one/jpro/platform/internal/util/CommandRunnerTests.java
rename to jpro-utils/src/test/java/one/jpro/platform/utils/test/CommandRunnerTests.java
index 0b9ed4ab..427d5760 100644
--- a/internal/util/src/test/java/one/jpro/platform/internal/util/CommandRunnerTests.java
+++ b/jpro-utils/src/test/java/one/jpro/platform/utils/test/CommandRunnerTests.java
@@ -1,5 +1,7 @@
-package one.jpro.platform.internal.util;
+package one.jpro.platform.utils.test;
+import one.jpro.platform.utils.CommandRunner;
+import one.jpro.platform.utils.PlatformUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.slf4j.Logger;
diff --git a/freeze-detector/src/test/java/one/jpro/platform/freezedetector/test/TestFreezeDetector.java b/jpro-utils/src/test/java/one/jpro/platform/utils/test/FreezeDetectorTests.java
similarity index 86%
rename from freeze-detector/src/test/java/one/jpro/platform/freezedetector/test/TestFreezeDetector.java
rename to jpro-utils/src/test/java/one/jpro/platform/utils/test/FreezeDetectorTests.java
index 04a63ca0..5e0ae14c 100644
--- a/freeze-detector/src/test/java/one/jpro/platform/freezedetector/test/TestFreezeDetector.java
+++ b/jpro-utils/src/test/java/one/jpro/platform/utils/test/FreezeDetectorTests.java
@@ -1,6 +1,6 @@
-package one.jpro.platform.freezedetector.test;
+package one.jpro.platform.utils.test;
-import one.jpro.platform.freezedetector.FreezeDetector;
+import one.jpro.platform.utils.FreezeDetector;
import org.junit.jupiter.api.Test;
import org.testfx.framework.junit5.ApplicationTest;
@@ -12,9 +12,9 @@
/**
* Tests the freeze detector.
*
- * @author Besmir Beqiri
+ * @author Florian Kirmaier
*/
-public class TestFreezeDetector extends ApplicationTest {
+public class FreezeDetectorTests extends ApplicationTest {
@Test
public void testFreezeDetector() throws InterruptedException {
diff --git a/jpro-utils/src/test/java/one/jpro/platform/utils/test/OpenLinkTests.java b/jpro-utils/src/test/java/one/jpro/platform/utils/test/OpenLinkTests.java
new file mode 100644
index 00000000..ff91ae94
--- /dev/null
+++ b/jpro-utils/src/test/java/one/jpro/platform/utils/test/OpenLinkTests.java
@@ -0,0 +1,98 @@
+package one.jpro.platform.utils.test;
+
+import one.jpro.platform.utils.OpenLink;
+import one.jpro.platform.utils.PlatformUtils;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+import org.mockito.MockedStatic;
+
+import java.io.IOException;
+import java.net.URI;
+
+import static org.mockito.Mockito.*;
+
+/**
+ * OpenLink tests.
+ *
+ * @author Besmir Beqiri
+ */
+public class OpenLinkTests {
+
+ // Mocked static instances for Runtime and PlatformUtils
+ private static MockedStatic runtimeMockedStatic;
+ private static MockedStatic platformUtilsMockedStatic;
+ private static final String TEST_URL = "http://www.example.com";
+
+ private Runtime runtime;
+
+ /**
+ * Initializes the static mocks before all tests run.
+ */
+ @BeforeAll
+ public static void init() {
+ runtimeMockedStatic = mockStatic(Runtime.class);
+ platformUtilsMockedStatic = mockStatic(PlatformUtils.class);
+ }
+
+ /**
+ * Cleans up the static mocks after all tests have run.
+ */
+ @AfterAll
+ public static void cleanup() {
+ if (runtimeMockedStatic != null) {
+ runtimeMockedStatic.close();
+ }
+ if (platformUtilsMockedStatic != null) {
+ platformUtilsMockedStatic.close();
+ }
+ }
+
+ /**
+ * Sets up the mock Runtime instance before each test.
+ */
+ @BeforeEach
+ public void setup() {
+ // Create a mock Runtime instance
+ runtime = mock(Runtime.class);
+ // Stub Runtime.getRuntime() to return the mocked Runtime
+ runtimeMockedStatic.when(Runtime::getRuntime).thenReturn(runtime);
+ }
+
+ @Test
+ public void testOpenURLOnMac() throws IOException {
+ when(PlatformUtils.isDesktop()).thenReturn(true);
+ when(PlatformUtils.isMac()).thenReturn(true);
+ when(PlatformUtils.isWindows()).thenReturn(false);
+ when(PlatformUtils.isLinux()).thenReturn(false);
+
+ OpenLink.openURL(URI.create(TEST_URL).toURL());
+
+ verify(runtime).exec(new String[]{"open", TEST_URL});
+ }
+
+ @Test
+ public void testOpenURLOnWindows() throws IOException {
+ when(PlatformUtils.isDesktop()).thenReturn(true);
+ when(PlatformUtils.isMac()).thenReturn(false);
+ when(PlatformUtils.isWindows()).thenReturn(true);
+ when(PlatformUtils.isLinux()).thenReturn(false);
+
+ OpenLink.openURL(URI.create(TEST_URL).toURL());
+
+ verify(runtime).exec(new String[]{"rundll32", "url.dll,FileProtocolHandler", TEST_URL});
+ }
+
+ @Test
+ public void testOpenURLOnLinux() throws IOException {
+ when(PlatformUtils.isDesktop()).thenReturn(true);
+ when(PlatformUtils.isMac()).thenReturn(false);
+ when(PlatformUtils.isWindows()).thenReturn(false);
+ when(PlatformUtils.isLinux()).thenReturn(true);
+
+ OpenLink.openURL(URI.create(TEST_URL).toURL());
+
+ verify(runtime).exec(new String[]{"xdg-open", TEST_URL});
+ }
+}
diff --git a/tree-showing/src/test/java/one/jpro/platform/treeshowing/TestTreeShowing.java b/jpro-utils/src/test/java/one/jpro/platform/utils/test/TreeShowingTests.java
similarity index 62%
rename from tree-showing/src/test/java/one/jpro/platform/treeshowing/TestTreeShowing.java
rename to jpro-utils/src/test/java/one/jpro/platform/utils/test/TreeShowingTests.java
index 928c21b9..4daf8600 100644
--- a/tree-showing/src/test/java/one/jpro/platform/treeshowing/TestTreeShowing.java
+++ b/jpro-utils/src/test/java/one/jpro/platform/utils/test/TreeShowingTests.java
@@ -1,32 +1,26 @@
-package one.jpro.platform.treeshowing;
+package one.jpro.platform.utils.test;
-import one.jpro.jmemorybuddy.JMemoryBuddy;
-import javafx.application.Platform;
import javafx.beans.property.BooleanProperty;
import javafx.scene.Group;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
+import one.jpro.jmemorybuddy.JMemoryBuddy;
+import one.jpro.platform.utils.TreeShowing;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
+import org.testfx.framework.junit5.ApplicationTest;
-import java.util.concurrent.CountDownLatch;
-import java.util.concurrent.atomic.AtomicReference;
-
-public class TestTreeShowing {
-
-
- @BeforeAll
- public static void startJavaFX() throws InterruptedException {
- CountDownLatch latch = new CountDownLatch(1);
- Platform.startup(latch::countDown);
- latch.await();
- }
+/**
+ * Tests for the {@link TreeShowing} utility class.
+ *
+ * @author Florian Kirmaier
+ */
+public class TreeShowingTests extends ApplicationTest {
@Test
public void simpleTest() {
- inFX(() -> {
+ interact(() -> {
Parent node = new Group();
BooleanProperty prop = TreeShowing.treeShowing(node);
Assertions.assertFalse(prop.get());
@@ -35,7 +29,7 @@ public void simpleTest() {
@Test
public void memoryTest1() {
- inFX(() -> JMemoryBuddy.memoryTest(checker -> {
+ interact(() -> JMemoryBuddy.memoryTest(checker -> {
Parent node = new Group();
BooleanProperty prop = TreeShowing.treeShowing(node);
@@ -46,7 +40,7 @@ public void memoryTest1() {
@Test
public void memoryTest2() {
- inFX(() -> JMemoryBuddy.memoryTest(checker -> {
+ interact(() -> JMemoryBuddy.memoryTest(checker -> {
Parent node = new Group();
BooleanProperty prop = TreeShowing.treeShowing(node);
Scene scene = new Scene(node);
@@ -63,11 +57,10 @@ public void memoryTest2() {
}));
}
-
- @Test
+ // @Test
public void memoryTest3() {
JMemoryBuddy.memoryTest(checker ->
- inFX(() -> {
+ interact(() -> {
Parent node = new Group();
BooleanProperty prop = TreeShowing.treeShowing(node);
Scene scene = new Scene(node);
@@ -87,26 +80,4 @@ public void memoryTest3() {
checker.assertCollectable(stage);
}));
}
-
- public void inFX(Runnable r) {
- CountDownLatch l = new CountDownLatch(1);
- AtomicReference ex = new AtomicReference<>();
- Platform.runLater(() -> {
- try {
- r.run();
- } catch (Throwable e) {
- ex.set(e);
- } finally {
- l.countDown();
- }
- });
- try {
- l.await();
- if (ex.get() != null) {
- throw new RuntimeException(ex.get());
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
}
diff --git a/settings.gradle b/settings.gradle
index 41ca9ecd..7f2c7aae 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -26,10 +26,7 @@ include "jpro-webrtc"
include "jpro-webrtc:example"
include "jpro-sipjs"
include "jpro-sipjs:example"
-include "internal:openlink"
-include "internal:util"
-include "tree-showing"
-include "freeze-detector"
+include "jpro-utils"
include "example"
//include "ensemble:samples"
//include "ensemble:site"
diff --git a/tree-showing/build.gradle b/tree-showing/build.gradle
deleted file mode 100644
index f4a3cda4..00000000
--- a/tree-showing/build.gradle
+++ /dev/null
@@ -1,15 +0,0 @@
-dependencies {
- implementation "one.jpro:jmemorybuddy:$JMEMORYBUDDY_VERSION"
-}
-
-publishing {
- publications {
- mavenJava(MavenPublication) {
- pom {
- name = 'Tree Showing'
- description = 'A utility module for JavaFX applications that provides properties and methods to ' +
- 'monitor and track the visibility status of nodes within the scene graph.'
- }
- }
- }
-}
diff --git a/tree-showing/src/main/java/module-info.java b/tree-showing/src/main/java/module-info.java
deleted file mode 100644
index ee0c50e2..00000000
--- a/tree-showing/src/main/java/module-info.java
+++ /dev/null
@@ -1,6 +0,0 @@
-module one.jpro.platform.treeshowing {
- requires javafx.controls;
- requires one.jpro.jmemorybuddy;
-
- exports one.jpro.platform.treeshowing;
-}
\ No newline at end of file