From 89cf70b6aca90c3e849fcd4b8c0d667c0d6cd7d8 Mon Sep 17 00:00:00 2001 From: Jurgen Date: Fri, 11 Nov 2022 16:07:28 +0200 Subject: [PATCH] Add DemoLauncher from afester --- richtextfx-demos/README.md | 2 +- richtextfx-demos/build.gradle | 215 ++++++++++++------ .../fxmisc/richtext/demo/DemoLauncher.java | 74 ++++++ .../demo/MultiCaretAndSelectionDemo.java | 4 + .../fxmisc/richtext/demo/ShowLineDemo.java | 4 + .../richtext/demo/SpellCheckingDemo.java | 3 +- 6 files changed, 228 insertions(+), 74 deletions(-) create mode 100644 richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/DemoLauncher.java diff --git a/richtextfx-demos/README.md b/richtextfx-demos/README.md index c6061b997..2e31608d4 100644 --- a/richtextfx-demos/README.md +++ b/richtextfx-demos/README.md @@ -17,7 +17,7 @@ Note: This page does not show all the demos in the package. Follow the instructi ### Instructions for running demos 1. Clone the repository: `git clone https://www.github.com/FXMisc/RichTextFX.git` -2. Checkout the latest release version: `git checkout v0.9.0` +2. Checkout the latest release version: `git checkout tagName` where tagName is the latest release tag (use `git tag` to get a list of available tags, and use the last one) 3. See the list of demos using a gradle task `./gradlew demos` 4. Run a demo using a gradle task: `./gradlew [Demo Name]` diff --git a/richtextfx-demos/build.gradle b/richtextfx-demos/build.gradle index f3ede9bcf..b18960182 100644 --- a/richtextfx-demos/build.gradle +++ b/richtextfx-demos/build.gradle @@ -1,5 +1,19 @@ plugins { - id 'java' + id 'application' + id 'org.openjfx.javafxplugin' version '0.0.10' +} + +javafx { + version = '11' + modules = [ 'javafx.controls'] +} + +// Common application JVM options - currently required to fix module dependency +// issues. This sets the required JVM options for all demo tasks specified below. +application { + applicationDefaultJvmArgs = ["--add-opens", "javafx.graphics/javafx.scene.text=ALL-UNNAMED", + "--add-exports", "javafx.graphics/com.sun.javafx.text=ALL-UNNAMED", + "--add-exports", "javafx.graphics/com.sun.javafx.scene.text=ALL-UNNAMED"] } dependencies { @@ -22,6 +36,12 @@ task fatJar(type: Jar, dependsOn: classes) { dependsOn ":richtextfx:jar" archiveAppendix = 'fat' + excludes = ['module-info.class'] + + manifest { + attributes( + 'Main-Class': 'org.fxmisc.richtext.demo.DemoLauncher') + } from sourceSets.main.output from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } } @@ -33,7 +53,7 @@ task demos(description: "Lists the names and the descriptions of the demos that doLast { // sort the demos first, so they can be added in the build file in any order def list = [] - tasks.withType(JavaExec) { + tasks.each { if (it.name.endsWith("Demo")) { list.add(it) } @@ -45,108 +65,161 @@ task demos(description: "Lists the names and the descriptions of the demos that } } -// To add a task for a demo, use the following template: +// To add a task for a demo, use the following template (and, also add the new +// demo class to org.fxmisc.richtext.demo.DemoLauncher so that it can be launched +// from the demo fat jar file): /* -task ClassNameDemo(type: JavaExec, dependsOn: classes, - description: "A description of what the demo does") { - mainClass = 'org.fxmisc.richtext.demo.ClassNameDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task ClassNameDemo(description: "A description of what the demo does") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.ClassNameDemo' + } + } } +ClassNameDemo.finalizedBy run */ -task JavaKeywordsDemo(type: JavaExec, dependsOn: classes, - description: "A CodeArea with Java syntax highlighting that is computed on the JavaFX Application Thread") { - mainClass = 'org.fxmisc.richtext.demo.JavaKeywordsDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task JavaKeywordsDemo(description: "A CodeArea with Java syntax highlighting that is computed on the JavaFX Application Thread") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.JavaKeywordsDemo' + } + } } +JavaKeywordsDemo.finalizedBy run -task JavaKeywordsAsyncDemo(type: JavaExec, dependsOn: classes, - description: "A CodeArea with Java syntax highlighting that is computed on a background thread") { - mainClass = 'org.fxmisc.richtext.demo.JavaKeywordsAsyncDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task JavaKeywordsAsyncDemo(description: "A CodeArea with Java syntax highlighting that is computed on a background thread") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.JavaKeywordsAsyncDemo' + } + } } +JavaKeywordsAsyncDemo.finalizedBy run -task XMLEditorDemo(type: JavaExec, dependsOn: classes, - description: "An area with XML syntax highlighting") { - mainClass = 'org.fxmisc.richtext.demo.XMLEditorDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task XMLEditorDemo(description: "An area with XML syntax highlighting") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.XMLEditorDemo' + } + } } +XMLEditorDemo.finalizedBy run -task ManualHighlightingDemo(type: JavaExec, dependsOn: classes, - description: "Manually highlight various parts of the text in an area via buttons") { - mainClass = 'org.fxmisc.richtext.demo.ManualHighlightingDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task ManualHighlightingDemo(description: "Manually highlight various parts of the text in an area via buttons") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.ManualHighlightingDemo' + } + } } +ManualHighlightingDemo.finalizedBy run -task RichTextDemo(type: JavaExec, dependsOn: classes, - description: "An area showing a large number of RichTextFX's features: " + +task RichTextDemo(description: "An area showing a large number of RichTextFX's features: " + "inlined images, rich text (e.g. text alignment and background colors, etc.), and save/load capabilities") { - mainClass = 'org.fxmisc.richtext.demo.richtext.RichTextDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.richtext.RichTextDemo' + } + } } +RichTextDemo.finalizedBy run -task PopupDemo(type: JavaExec, dependsOn: classes, - description: "A popup that follows the caret and selection when they move") { - mainClass = 'org.fxmisc.richtext.demo.PopupDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task PopupDemo(description: "A popup that follows the caret and selection when they move") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.PopupDemo' + } + } } +PopupDemo.finalizedBy run -task TooltipDemo(type: JavaExec, dependsOn: classes, - description: "Tells you the letter over which the mouse is hovering") { - mainClass = 'org.fxmisc.richtext.demo.TooltipDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task TooltipDemo(description: "Tells you the letter over which the mouse is hovering") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.TooltipDemo' + } + } } +TooltipDemo.finalizedBy run -task HyperlinkAreaDemo(type: JavaExec, dependsOn: classes, - description: "An area with hyperlinks that open to their corresponding link") { - mainClass = 'org.fxmisc.richtext.demo.hyperlink.HyperlinkDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task HyperlinkAreaDemo(description: "An area with hyperlinks that open to their corresponding link") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.hyperlink.HyperlinkDemo' + } + } } +HyperlinkAreaDemo.finalizedBy run -task LineIndicatorDemo(type: JavaExec, dependsOn: classes, - description: "Line numbers appear to left of each paragraph and a triangle appears on the same paragraph as the caret") { - mainClass = 'org.fxmisc.richtext.demo.lineindicator.LineIndicatorDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task LineIndicatorDemo(description: "Line numbers appear to left of each paragraph and a triangle appears on the same paragraph as the caret") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.lineindicator.LineIndicatorDemo' + } + } } +LineIndicatorDemo.finalizedBy run -task CloneDemo(type: JavaExec, dependsOn: classes, - description: "Two areas that can modify and show the same underlying document") { - mainClass = 'org.fxmisc.richtext.demo.CloneDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task CloneDemo( description: "Two areas that can modify and show the same underlying document") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.CloneDemo' + } + } } +CloneDemo.finalizedBy run -task FontSizeSwitcherDemo(type: JavaExec, dependsOn: classes, - description: "Change the font size of the entire area.") { - mainClass = 'org.fxmisc.richtext.demo.FontSizeSwitcherDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task FontSizeSwitcherDemo(description: "Change the font size of the entire area.") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.FontSizeSwitcherDemo' + } + } } +FontSizeSwitcherDemo.finalizedBy run -task MultiCaretAndSelectionNameDemo(type: JavaExec, dependsOn: classes, - description: "Add and display multiple carets and selections with different style classes in the same area") { - mainClass = 'org.fxmisc.richtext.demo.MultiCaretAndSelectionDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task MultiCaretAndSelectionNameDemo(description: "Add and display multiple carets and selections with different style classes in the same area") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.MultiCaretAndSelectionDemo' + } + } } +MultiCaretAndSelectionNameDemo.finalizedBy run -task OverrideBehaviorDemo(type: JavaExec, dependsOn: classes, - description: "Overrides the area's default behavior and demonstrates some things of which to be aware") { - mainClass = 'org.fxmisc.richtext.demo.OverrideBehaviorDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task OverrideBehaviorDemo(description: "Overrides the area's default behavior and demonstrates some things of which to be aware") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.OverrideBehaviorDemo' + } + } } +OverrideBehaviorDemo.finalizedBy run -task ShowLineDemo(type: JavaExec, dependsOn: classes, - description: "Force a specific part of the underlying document to be rendered to the screen.") { - mainClass = 'org.fxmisc.richtext.demo.ShowLineDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task ShowLineDemo(description: "Force a specific part of the underlying document to be rendered to the screen.") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.ShowLineDemo' + } + } } +ShowLineDemo.finalizedBy run -task SpellCheckingDemo(type: JavaExec, dependsOn: classes, - description: "Shows how to add a red squiggle underneath misspelled words") { - mainClass = 'org.fxmisc.richtext.demo.SpellCheckingDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task SpellCheckingDemo(description: "Shows how to add a red squiggle underneath misspelled words") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.SpellCheckingDemo' + } + } } +SpellCheckingDemo.finalizedBy run -task BracketHighlighterDemo(type: JavaExec, dependsOn: classes, - description: "Shows how to highlight matching brackets") { - mainClass = 'org.fxmisc.richtext.demo.brackethighlighter.BracketHighlighterDemo' - classpath = files(sourceSets.main.output, configurations.runtimeClasspath) +task BracketHighlighterDemo(description: "Shows how to highlight matching brackets") { + doLast() { + application { + mainClass = 'org.fxmisc.richtext.demo.brackethighlighter.BracketHighlighterDemo' + } + } } +BracketHighlighterDemo.finalizedBy run diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/DemoLauncher.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/DemoLauncher.java new file mode 100644 index 000000000..b5c8d9a3c --- /dev/null +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/DemoLauncher.java @@ -0,0 +1,74 @@ +package org.fxmisc.richtext.demo; + +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +import org.reactfx.util.Tuple2; +import static org.reactfx.util.Tuples.*; + +/** + * This class serves as the entry point for launching the various demos. + * It is primarily used when creating a FAT jar (or executable jar) for the + * demos. + */ +public class DemoLauncher { + + @SuppressWarnings("serial") + private static final Map>> demoMap = new HashMap<>() {{ + /** + * When launched from the JVM launcher directly, all the Demo classes would not necessarily require a + * main() method - the JVM launcher would take care of it. However, since we use our own launcher + * class here, the main() method in each individual class *is* required - simply calling the + * launch() method does NOT work! + */ + put("JavaKeywordsDemo", t("A CodeArea with Java syntax highlighting that is computed on the JavaFX Application Thread", + org.fxmisc.richtext.demo.JavaKeywordsDemo::main)); + put("JavaKeywordsAsyncDemo", t("A CodeArea with Java syntax highlighting that is computed on a background thread", + org.fxmisc.richtext.demo.JavaKeywordsAsyncDemo::main)); + put("XMLEditorDemo", t("An area with XML syntax highlighting", + org.fxmisc.richtext.demo.XMLEditorDemo::main)); + put("ManualHighlightingDemo", t("Manually highlight various parts of the text in an area via buttons", + org.fxmisc.richtext.demo.ManualHighlightingDemo::main)); + put("RichTextDemo", t("An area showing a large number of RichTextFX's features: inlined images, rich text (e.g. text alignment and background colors, etc.), and save/load capabilities", + org.fxmisc.richtext.demo.richtext.RichTextDemo::main)); + put("PopupDemo", t("A popup that follows the caret and selection when they move", + org.fxmisc.richtext.demo.PopupDemo::main)); + put("TooltipDemo", t("Tells you the letter over which the mouse is hovering", + org.fxmisc.richtext.demo.TooltipDemo::main)); + put("HyperlinkAreaDemo", t("An area with hyperlinks that open to their corresponding link", + org.fxmisc.richtext.demo.hyperlink.HyperlinkDemo::main)); + put("LineIndicatorDemo", t("Line numbers appear to left of each paragraph and a triangle appears on the same paragraph as the caret", + org.fxmisc.richtext.demo.lineindicator.LineIndicatorDemo::main)); + put("CloneDemo", t("Two areas that can modify and show the same underlying document", + org.fxmisc.richtext.demo.CloneDemo::main)); + put("FontSizeSwitcherDemo", t("Change the font size of the entire area.", + org.fxmisc.richtext.demo.FontSizeSwitcherDemo::main)); + put("MultiCaretAndSelectionNameDemo", t("Add and display multiple carets and selections with different style classes in the same area", + org.fxmisc.richtext.demo.MultiCaretAndSelectionDemo::main)); + put("OverrideBehaviorDemo", t("Overrides the area's default behavior and demonstrates some things of which to be aware", + org.fxmisc.richtext.demo.OverrideBehaviorDemo::main)); + put("ShowLineDemo", t("Force a specific part of the underlying document to be rendered to the screen.", + org.fxmisc.richtext.demo.ShowLineDemo::main)); + put("SpellCheckingDemo", t("Shows how to add a red squiggle underneath misspelled words", + org.fxmisc.richtext.demo.SpellCheckingDemo::main)); + put("BracketHighlighterDemo", t("Shows how to highlight matching brackets", + org.fxmisc.richtext.demo.brackethighlighter.BracketHighlighterDemo::main)); + }}; + + private final static String[] noArgs = new String[0]; + + public static void main(String[] args) { + if (args.length == 0) { + demoMap.entrySet().forEach(e -> System.out.printf("%s - %s\n", e.getKey(), e.getValue().get1())); + } else { + final Tuple2> demoData = demoMap.get(args[0]); + if (demoData == null) { + System.err.printf("No such demo: %s", args[0]); + } else { + Consumer mainMethod = demoData.get2(); + mainMethod.accept(noArgs); + } + } + } +} diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/MultiCaretAndSelectionDemo.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/MultiCaretAndSelectionDemo.java index 27935c64c..485b2fa2c 100644 --- a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/MultiCaretAndSelectionDemo.java +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/MultiCaretAndSelectionDemo.java @@ -14,6 +14,10 @@ public class MultiCaretAndSelectionDemo extends Application { private InlineCssTextArea area; + public static void main(String[] args) { + launch(args); + } + @Override public void start(Stage primaryStage) { // initialize area with some lines of text diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/ShowLineDemo.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/ShowLineDemo.java index f22480a89..a63f6520e 100644 --- a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/ShowLineDemo.java +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/ShowLineDemo.java @@ -53,6 +53,10 @@ public int getTextAsInt() { field.setPromptText("Input a number to indicate which line you want to show"); } + public static void main(String[] args) { + launch(args); + } + @Override public void start(Stage primaryStage) throws Exception { StringBuilder sb = new StringBuilder(); diff --git a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/SpellCheckingDemo.java b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/SpellCheckingDemo.java index c68c2661d..2f43b001b 100644 --- a/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/SpellCheckingDemo.java +++ b/richtextfx-demos/src/main/java/org/fxmisc/richtext/demo/SpellCheckingDemo.java @@ -20,7 +20,6 @@ import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.stage.Stage; -import org.reactfx.Subscription; public class SpellCheckingDemo extends Application { @@ -35,7 +34,7 @@ public void start(Stage primaryStage) { StyleClassedTextArea textArea = new StyleClassedTextArea(); textArea.setWrapText(true); - Subscription cleanupWhenFinished = textArea.multiPlainChanges() + textArea.multiPlainChanges() .successionEnds(Duration.ofMillis(500)) .subscribe(change -> { textArea.setStyleSpans(0, computeHighlighting(textArea.getText()));