Remove reactfx dependency

The reactfx was a 0.33MB dependency / 238 Java source files.

We only used it for FxTimer helper and to measure FPS in development mode.

The small FxTimer class got copied over into the project,
so there is no change in semantics.

The FPS measurement got replaced w/ com.sun.javafx.perf.PerformanceTracker,
an internal but long stable part of JavaFx. This is probably not a problem,
because it only concerns a rarely used, developer feature.
This commit is contained in:
battleofwizards 2019-09-17 12:56:56 +02:00
parent 736da2a006
commit 9ea6b2163e
No known key found for this signature in database
GPG Key ID: 58B1485148D203E1
8 changed files with 196 additions and 16 deletions

View File

@ -64,7 +64,6 @@ configure(subprojects) {
protobufVersion = '3.9.1'
pushyVersion = '0.13.2'
qrgenVersion = '1.3'
reactfxVersion = '2.0-M3'
sarxosVersion = '0.3.12'
slf4jVersion = '1.7.22'
sparkVersion = '2.5.2'
@ -290,7 +289,6 @@ configure(project(':desktop')) {
dependencies {
compile project(':core')
compile "org.controlsfx:controlsfx:$controlsfxVersion"
compile "org.reactfx:reactfx:$reactfxVersion"
compile "net.glxn:qrgen:$qrgenVersion"
compile "de.jensd:fontawesomefx:$fontawesomefxVersion"
compile "de.jensd:fontawesomefx-commons:$fontawesomefxCommonsVersion"

View File

@ -0,0 +1,104 @@
package bisq.common.reactfx;
import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.util.Duration;
/**
* Provides factory methods for timers that are manipulated from and execute
* their action on the JavaFX application thread.
*
* Copied from:
* https://github.com/TomasMikula/ReactFX/blob/537fffdbb2958a77dfbca08b712bb2192862e960/reactfx/src/main/java/org/reactfx/util/FxTimer.java
*
*/
public class FxTimer implements Timer {
/**
* Prepares a (stopped) timer that lasts for {@code delay} and whose action runs when timer <em>ends</em>.
*/
public static Timer create(java.time.Duration delay, Runnable action) {
return new FxTimer(delay, delay, action, 1);
}
/**
* Equivalent to {@code create(delay, action).restart()}.
*/
public static Timer runLater(java.time.Duration delay, Runnable action) {
Timer timer = create(delay, action);
timer.restart();
return timer;
}
/**
* Prepares a (stopped) timer that lasts for {@code interval} and that executes the given action periodically
* when the timer <em>ends</em>.
*/
public static Timer createPeriodic(java.time.Duration interval, Runnable action) {
return new FxTimer(interval, interval, action, Animation.INDEFINITE);
}
/**
* Equivalent to {@code createPeriodic(interval, action).restart()}.
*/
public static Timer runPeriodically(java.time.Duration interval, Runnable action) {
Timer timer = createPeriodic(interval, action);
timer.restart();
return timer;
}
/**
* Prepares a (stopped) timer that lasts for {@code interval} and that executes the given action periodically
* when the timer <em>starts</em>.
*/
public static Timer createPeriodic0(java.time.Duration interval, Runnable action) {
return new FxTimer(java.time.Duration.ZERO, interval, action, Animation.INDEFINITE);
}
/**
* Equivalent to {@code createPeriodic0(interval, action).restart()}.
*/
public static Timer runPeriodically0(java.time.Duration interval, Runnable action) {
Timer timer = createPeriodic0(interval, action);
timer.restart();
return timer;
}
private final Duration actionTime;
private final Timeline timeline;
private final Runnable action;
private long seq = 0;
private FxTimer(java.time.Duration actionTime, java.time.Duration period, Runnable action, int cycles) {
this.actionTime = Duration.millis(actionTime.toMillis());
this.timeline = new Timeline();
this.action = action;
timeline.getKeyFrames().add(new KeyFrame(this.actionTime)); // used as placeholder
if (period != actionTime) {
timeline.getKeyFrames().add(new KeyFrame(Duration.millis(period.toMillis())));
}
timeline.setCycleCount(cycles);
}
@Override
public void restart() {
stop();
long expected = seq;
timeline.getKeyFrames().set(0, new KeyFrame(actionTime, ae -> {
if(seq == expected) {
action.run();
}
}));
timeline.play();
}
@Override
public void stop() {
timeline.stop();
++seq;
}
}

View File

@ -0,0 +1,10 @@
Copyright (c) 2013-2014, Tomas Mikula
All rights reserved.
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View File

@ -0,0 +1,6 @@
This package is a very minimal subset of the external library `org.reactfx`.
Two small files from `org.reactfx` were embedded into the project
to avoid having it as dependency:
[https://github.com/TomasMikula/ReactFX]

View File

@ -0,0 +1,66 @@
package bisq.common.reactfx;
/**
* Timer represents a delayed action. This means that every timer has an
* associated action and an associated delay. Action and delay are specified
* on timer creation.
*
* <p>Every timer also has an associated thread (such as JavaFX application
* thread or a single-thread executor's thread). Timer may only be accessed
* from its associated thread. Timer's action is executed on its associated
* thread, too. This design allows to implement guarantees provided by
* {@link #stop()}.
*
* Copied from:
* https://raw.githubusercontent.com/TomasMikula/ReactFX/537fffdbb2958a77dfbca08b712bb2192862e960/reactfx/src/main/java/org/reactfx/util/Timer.java*
*/
public interface Timer {
/**
* Schedules the associated action to be executed after the associated
* delay. If the action is already scheduled but hasn't been executed yet,
* the timeout is reset, so that the action won't be executed before the
* full delay from now.
*/
void restart();
/**
* If the associated action has been scheduled for execution but not yet
* executed, this method prevents it from being executed at all. This is
* also true in case the timer's timeout has already expired, but the
* associated action hasn't had a chance to be executed on the associated
* thread. Note that this is a stronger guarantee than the one given by
* {@link javafx.animation.Animation#stop()}:
*
* <pre>
* {@code
* Timeline timeline = new Timeline(new KeyFrame(
* Duration.millis(1000),
* ae -> System.out.println("FIRED ANYWAY")));
* timeline.play();
*
* // later on the JavaFX application thread,
* // but still before the action has been executed
* timeline.stop();
*
* // later, "FIRED ANYWAY" may still be printed
* }
* </pre>
*
* In contrast, using the {@link FxTimer}, the action is guaranteed not to
* be executed after {@code stop()}:
* <pre>
* {@code
* Timer timer = FxTimer.runLater(
* Duration.ofMillis(1000),
* () -> System.out.println("FIRED"));
*
* // later on the JavaFX application thread,
* // but still before the action has been executed
* timer.stop();
*
* // "FIRED" is guaranteed *not* to be printed
* }
* </pre>
*/
void stop();
}

View File

@ -57,8 +57,6 @@ import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.name.Names;
import org.reactfx.EventStreams;
import javafx.application.Application;
import javafx.stage.Modality;
@ -80,6 +78,8 @@ import java.awt.Rectangle;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
import com.sun.javafx.perf.PerformanceTracker;
import org.slf4j.LoggerFactory;
import ch.qos.logback.classic.Level;
@ -404,14 +404,12 @@ public class BisqApp extends Application implements UncaughtExceptionHandler {
private void showFPSWindow(Scene scene) {
Label label = new AutoTooltipLabel();
EventStreams.animationTicks()
.latestN(100)
.map(ticks -> {
int n = ticks.size() - 1;
return n * 1_000_000_000.0 / (ticks.get(n) - ticks.get(0));
})
.map(d -> String.format("FPS: %.3f", d)) // Don't translate, just for dev
.feedTo(label.textProperty());
PerformanceTracker performance = PerformanceTracker.getSceneTracker(scene);
UserThread.runPeriodically(() -> {
float fps = performance.getInstantPulses();
label.setText(String.format("FPS: %.1f", fps));
}, 1000, TimeUnit.MILLISECONDS);
Pane root = new StackPane();
root.getChildren().add(label);

View File

@ -18,8 +18,7 @@
package bisq.desktop.common;
import bisq.common.Timer;
import org.reactfx.util.FxTimer;
import bisq.common.reactfx.FxTimer;
import java.time.Duration;
@ -28,7 +27,7 @@ import org.slf4j.LoggerFactory;
public class UITimer implements Timer {
private final Logger log = LoggerFactory.getLogger(UITimer.class);
private org.reactfx.util.Timer timer;
private bisq.common.reactfx.Timer timer;
public UITimer() {
}

View File

@ -15,7 +15,6 @@
dependencyVerification {
verify = [
'org.controlsfx:controlsfx:b98f1c9507c05600f80323674b33d15674926c71b0116f70085b62bdacf1e573',
'org.reactfx:reactfx:81ec8fe545d65661222735711114c2ce427e2187a65f1722e8ac4e4805beeca3',
'net.glxn:qrgen:c85d9d8512d91e8ad11fe56259a7825bd50ce0245447e236cf168d1b17591882',
'de.jensd:fontawesomefx:73bacc991a0a6f5cf0f911767c8db161e0949dbca61e8371eb4342e3da96887b',
'de.jensd:fontawesomefx-materialdesignfont:dbad8dfdd1c85e298d5bbae25b2399aec9e85064db57b2427d10f3815aa98752',