Skip to content

Commit c05adc1

Browse files
AustinShalitJLLeitschuh
authored andcommitted
Add a loading screen (#629)
* Add a loading screen * Preloader in its own jar * ProgressBar displays progress
1 parent 28d7e0b commit c05adc1

File tree

7 files changed

+132
-16
lines changed

7 files changed

+132
-16
lines changed

build.gradle

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,19 @@ project(":core") {
300300
}
301301
}
302302

303+
project (":ui:preloader") {
304+
apply plugin: 'java'
305+
apply plugin: 'idea'
306+
apply plugin: 'jacoco'
307+
apply plugin: 'application'
308+
309+
task run(overwrite: true, type: JavaExec) {
310+
classpath = sourceSets.main.runtimeClasspath
311+
main = 'edu.wpi.grip.preloader.GripPreloader'
312+
args 'windowed'
313+
}
314+
}
315+
303316
project(":ui") {
304317
apply plugin: 'java'
305318
apply plugin: 'idea'
@@ -313,6 +326,7 @@ project(":ui") {
313326

314327
dependencies {
315328
compile project(path: ':core', configuration: 'shadow')
329+
compile project(path: ':ui:preloader')
316330
ideProvider project(path: ':core', configuration: 'compile')
317331
compile group: 'org.controlsfx', name: 'controlsfx', version: '8.40.11'
318332
compile group: 'com.hierynomus', name: 'sshj', version: '0.16.0'
@@ -324,6 +338,7 @@ project(":ui") {
324338
}
325339

326340
evaluationDependsOn(':core')
341+
evaluationDependsOnChildren()
327342
compileTestJava.dependsOn tasks.getByPath(':core:testClasses')
328343

329344
idea.module {
@@ -362,6 +377,8 @@ project(":ui") {
362377
// and as such, would be useless.
363378
// See: https://plumbr.eu/blog/java/on-a-quest-for-missing-stacktraces
364379
jvmArgs = ["-XX:-OmitStackTraceInFastThrow"]
380+
381+
systemProperties = ['javafx.preloader':'edu.wpi.grip.preloader.GripPreloader']
365382
}
366383
mainClassName = javafx.mainClass
367384

settings.gradle

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
include 'core', 'ui'
1+
include 'core', 'ui', 'ui:preloader'
22
rootProject.name = 'GRIP'
3-
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package edu.wpi.grip.preloader;
2+
3+
import java.io.IOException;
4+
import javafx.application.Preloader;
5+
import javafx.fxml.FXMLLoader;
6+
import javafx.scene.Parent;
7+
import javafx.scene.Scene;
8+
import javafx.scene.control.ProgressBar;
9+
import javafx.stage.Stage;
10+
import javafx.stage.StageStyle;
11+
12+
public final class GripPreloader extends Preloader {
13+
14+
private ProgressBar progressBar;
15+
private Stage preloaderStage;
16+
17+
public static void main(String[] args) {
18+
launch(args);
19+
}
20+
21+
@Override
22+
public void start(Stage preloaderStage) throws IOException {
23+
Parent root = FXMLLoader.load(GripPreloader.class.getResource("Preloader.fxml"));
24+
Scene scene = new Scene(root);
25+
26+
progressBar = (ProgressBar) root.getChildrenUnmodifiable().filtered(
27+
p -> p instanceof ProgressBar).get(0);
28+
29+
System.setProperty("prism.lcdtext", "false");
30+
31+
if (getParameters().getRaw().contains("windowed")) {
32+
preloaderStage.initStyle(StageStyle.UTILITY);
33+
} else {
34+
preloaderStage.initStyle(StageStyle.TRANSPARENT);
35+
}
36+
preloaderStage.setScene(scene);
37+
preloaderStage.setAlwaysOnTop(true);
38+
preloaderStage.setResizable(false);
39+
preloaderStage.show();
40+
41+
this.preloaderStage = preloaderStage;
42+
}
43+
44+
@Override
45+
public void handleApplicationNotification(PreloaderNotification pn) {
46+
if (pn instanceof ProgressNotification) {
47+
progressBar.setProgress(((ProgressNotification) pn).getProgress());
48+
} else if (pn instanceof StateChangeNotification
49+
&& ((StateChangeNotification) pn).getType() == StateChangeNotification.Type.BEFORE_START) {
50+
preloaderStage.hide();
51+
}
52+
}
53+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
.root {
2+
-fx-padding: 25;
3+
}
4+
5+
.progress-bar {
6+
-fx-padding: 25 0 0 0;
7+
-fx-accent: #6C8058;
8+
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
3+
<?import java.net.URL?>
4+
<?import javafx.scene.control.ProgressBar?>
5+
<?import javafx.scene.image.Image?>
6+
<?import javafx.scene.image.ImageView?>
7+
<?import javafx.scene.layout.VBox?>
8+
<?import javafx.stage.Screen?>
9+
<VBox id="root" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1">
10+
<children>
11+
<ImageView fitWidth="${screen.visualBounds.width / 4}" pickOnBounds="true" preserveRatio="true">
12+
<image>
13+
<Image url="@grip.png" />
14+
</image>
15+
<fx:define>
16+
<Screen fx:factory="getPrimary" fx:id="screen"/>
17+
</fx:define>
18+
</ImageView>
19+
<ProgressBar id="progress-bar" maxWidth="1.7976931348623157E308" />
20+
</children>
21+
<stylesheets>
22+
<URL value="@Preloader.css" />
23+
</stylesheets>
24+
</VBox>
14.4 KB
Loading

ui/src/main/java/edu/wpi/grip/ui/Main.java

Lines changed: 29 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import java.util.logging.Logger;
3131
import javafx.application.Application;
3232
import javafx.application.Platform;
33+
import javafx.application.Preloader;
3334
import javafx.fxml.FXMLLoader;
3435
import javafx.scene.Parent;
3536
import javafx.scene.Scene;
@@ -58,14 +59,14 @@ public class Main extends Application {
5859
@Inject private GripServer server;
5960
@Inject private HttpPipelineSwitcher pipelineSwitcher;
6061
private Parent root;
62+
private boolean headless;
6163

6264
public static void main(String[] args) {
6365
launch(args);
6466
}
6567

6668
@Override
67-
@SuppressWarnings("PMD.SignatureDeclareThrowsException")
68-
public void start(Stage stage) throws Exception {
69+
public void init() throws IOException {
6970
List<String> parameters = new ArrayList<>(getParameters().getRaw());
7071

7172
if (parameters.contains("--headless")) {
@@ -76,35 +77,28 @@ public void start(Stage stage) throws Exception {
7677
injector.injectMembers(this);
7778

7879
parameters.remove("--headless");
80+
headless = true;
7981
} else {
8082
// Otherwise, run with both the core and UI modules, and show the JavaFX stage
8183
injector = Guice.createInjector(Modules.override(new GripCoreModule(), new GripFileModule(),
8284
new GripSourcesHardwareModule()).with(new GripNetworkModule(), new GripUiModule()));
83-
8485
injector.injectMembers(this);
86+
notifyPreloader(new Preloader.ProgressNotification(0.15));
8587

8688
System.setProperty("prism.lcdtext", "false");
8789
Font.loadFont(this.getClass().getResource("roboto/Roboto-Regular.ttf").openStream(), -1);
8890
Font.loadFont(this.getClass().getResource("roboto/Roboto-Bold.ttf").openStream(), -1);
8991
Font.loadFont(this.getClass().getResource("roboto/Roboto-Italic.ttf").openStream(), -1);
9092
Font.loadFont(this.getClass().getResource("roboto/Roboto-BoldItalic.ttf").openStream(), -1);
91-
92-
root = FXMLLoader.load(Main.class.getResource("MainWindow.fxml"), null, null,
93-
injector::getInstance);
94-
root.setStyle("-fx-font-size: " + DPIUtility.FONT_SIZE + "px");
95-
96-
// If this isn't here this can cause a deadlock on windows. See issue #297
97-
stage.setOnCloseRequest(event -> SafeShutdown.exit(0, Platform::exit));
98-
stage.setTitle("GRIP Computer Vision Engine");
99-
stage.getIcons().add(new Image("/edu/wpi/grip/ui/icons/grip.png"));
100-
stage.setScene(new Scene(root));
101-
stage.show();
93+
notifyPreloader(new Preloader.ProgressNotification(0.3));
10294
}
10395

10496
operations.addOperations();
10597
cvOperations.addOperations();
98+
notifyPreloader(new Preloader.ProgressNotification(0.45));
10699
server.addHandler(pipelineSwitcher);
107100
server.start();
101+
notifyPreloader(new Preloader.ProgressNotification(0.6));
108102

109103
// If there was a file specified on the command line, open it immediately
110104
if (!parameters.isEmpty()) {
@@ -117,6 +111,27 @@ public void start(Stage stage) throws Exception {
117111
}
118112

119113
pipelineRunner.startAsync();
114+
notifyPreloader(new Preloader.ProgressNotification(0.75));
115+
}
116+
117+
@Override
118+
public void start(Stage stage) throws IOException {
119+
if (!headless) {
120+
root = FXMLLoader.load(Main.class.getResource("MainWindow.fxml"), null, null,
121+
injector::getInstance);
122+
root.setStyle("-fx-font-size: " + DPIUtility.FONT_SIZE + "px");
123+
notifyPreloader(new Preloader.ProgressNotification(0.9));
124+
125+
// If this isn't here this can cause a deadlock on windows. See issue #297
126+
stage.setOnCloseRequest(event -> SafeShutdown.exit(0, Platform::exit));
127+
stage.setTitle("GRIP Computer Vision Engine");
128+
stage.getIcons().add(new Image("/edu/wpi/grip/ui/icons/grip.png"));
129+
stage.setScene(new Scene(root));
130+
notifyPreloader(new Preloader.ProgressNotification(1.0));
131+
notifyPreloader(new Preloader.StateChangeNotification(
132+
Preloader.StateChangeNotification.Type.BEFORE_START));
133+
stage.show();
134+
}
120135
}
121136

122137
public void stop() {

0 commit comments

Comments
 (0)