From 5ce9f65b7411eaad8f45d2788c95b9c55fa1aec3 Mon Sep 17 00:00:00 2001 From: Patrick Plenefisch Date: Fri, 24 Mar 2023 16:13:16 -0400 Subject: [PATCH] feat: Add JRuby controller skeleton generation (#596) --- .../kit/skeleton/AbstractSkeletonCreator.java | 6 +- .../kit/skeleton/SkeletonConverter.java | 37 +++ .../kit/skeleton/SkeletonCreator.java | 5 +- .../kit/skeleton/SkeletonCreatorJRuby.java | 259 ++++++++++++++++++ .../skeleton/SkeletonFileNameProposal.java | 5 +- .../kit/skeleton/SkeletonSettings.java | 4 +- .../kit/skeleton/SkeletonBufferJRubyTest.java | 129 +++++++++ .../kit/skeleton/skeleton_ruby_comments.txt | 17 ++ .../kit/skeleton/skeleton_ruby_full.txt | 25 ++ .../skeleton/skeleton_ruby_full_comments.txt | 33 +++ .../kit/skeleton/skeleton_ruby_nested.txt | 13 + 11 files changed, 526 insertions(+), 7 deletions(-) create mode 100644 kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonConverter.java create mode 100644 kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonCreatorJRuby.java create mode 100644 kit/src/test/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonBufferJRubyTest.java create mode 100644 kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_comments.txt create mode 100644 kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_full.txt create mode 100644 kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_full_comments.txt create mode 100644 kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_nested.txt diff --git a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/AbstractSkeletonCreator.java b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/AbstractSkeletonCreator.java index 3ad02e053..6ac4515d8 100644 --- a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/AbstractSkeletonCreator.java +++ b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/AbstractSkeletonCreator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Gluon and/or its affiliates. + * Copyright (c) 2021, 2023, Gluon and/or its affiliates. * All rights reserved. Use is subject to license terms. * * This file is available and licensed under the following license: @@ -38,13 +38,13 @@ import java.util.Map; import java.util.ResourceBundle; -abstract class AbstractSkeletonCreator { +abstract class AbstractSkeletonCreator implements SkeletonConverter { static final String NL = System.lineSeparator(); static final String INDENT = " "; //NOI18N static final String FXML_ANNOTATION = "@FXML"; - String createFrom(SkeletonContext context) { + public String createFrom(SkeletonContext context) { final StringBuilder sb = new StringBuilder(); appendHeaderComment(context, sb); diff --git a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonConverter.java b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonConverter.java new file mode 100644 index 000000000..903990d5e --- /dev/null +++ b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonConverter.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023, Gluon and/or its affiliates. + * All rights reserved. Use is subject to license terms. + * + * This file is available and licensed under the following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - 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. + * - Neither the name of Oracle Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 + * OWNER 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. + */ +package com.oracle.javafx.scenebuilder.kit.skeleton; + +@FunctionalInterface +public interface SkeletonConverter { + String createFrom(SkeletonContext context); +} diff --git a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonCreator.java b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonCreator.java index ba0cdd142..4521722e2 100644 --- a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonCreator.java +++ b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonCreator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Gluon and/or its affiliates. + * Copyright (c) 2021, 2023, Gluon and/or its affiliates. * All rights reserved. Use is subject to license terms. * * This file is available and licensed under the following license: @@ -35,6 +35,7 @@ class SkeletonCreator { private final SkeletonCreatorJava skeletonCreatorJava = new SkeletonCreatorJava(); private final SkeletonCreatorKotlin skeletonCreatorKotlin = new SkeletonCreatorKotlin(); + private final SkeletonCreatorJRuby skeletonCreatorJRuby = new SkeletonCreatorJRuby(); /** * @return a code skeleton for the given context @@ -45,6 +46,8 @@ String createFrom(SkeletonContext context) { return skeletonCreatorJava.createFrom(context); case KOTLIN: return skeletonCreatorKotlin.createFrom(context); + case JRUBY: + return skeletonCreatorJRuby.createFrom(context); default: throw new IllegalArgumentException("Language not supported: " + context.getSettings().getLanguage()); } diff --git a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonCreatorJRuby.java b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonCreatorJRuby.java new file mode 100644 index 000000000..866b21a8d --- /dev/null +++ b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonCreatorJRuby.java @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2023, Gluon and/or its affiliates. + * All rights reserved. Use is subject to license terms. + * + * This file is available and licensed under the following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - 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. + * - Neither the name of Oracle Corporation nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 + * OWNER 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. + */ +package com.oracle.javafx.scenebuilder.kit.skeleton; + +import com.oracle.javafx.scenebuilder.kit.i18n.I18N; + +import java.lang.reflect.TypeVariable; +import java.net.URL; +import java.util.Map; +import java.util.ResourceBundle; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class SkeletonCreatorJRuby implements SkeletonConverter { + + static final String NL = System.lineSeparator(); + static final String INDENT = " "; //NOI18N + + public String createFrom(SkeletonContext context) { + + final StringBuilder sb = new StringBuilder(); + appendHeaderComment(context, sb); + // Ruby supports packages... but we ignore it here because Java package != Ruby Module and + // equating the two can cause confusion. Let the user fix it up themselves + appendClass(context, sb); + + return sb.toString(); + } + + public String createApplicationFrom(SkeletonContext context) { + + return "require 'jrubyfx'\n" + + "\n" + + createFrom(context) + + "\n" + + "fxml_root File.dirname(__FILE__) # or wherever you save the fxml file to\n" + + "\n" + + "class " + makeClassName(context) + "Application < JRubyFX::Application\n" + + " def start(stage)\n" + + " " + makeClassName(context) + ".load_into(stage)\n" + + " #stage.title = \"" + makeClassName(context) + "\"\n" + + " stage.show\n" + + " end\n" + + " launch\n" + + "end\n"; + } + + static Pattern importExtractor = Pattern.compile("import (([^.]+)\\..*)"); + + void appendImports(SkeletonContext context, StringBuilder sb) { + boolean output = false; + // Optional, really, as JRubyFX imports them by default + // Only "import" non-javafx ones in a comment + for (String importStatement : context.getImports()) { + Matcher matcher = importExtractor.matcher(importStatement); + matcher.matches(); + String rootName = matcher.group(2); + if (rootName.equals("javafx")) + continue; // JRubyFX already imports these + sb.append(INDENT).append("# java_import '").append(matcher.group(1)).append("'").append(NL); + output = true; + } + if (output) + sb.append(NL); + } + + + void appendHeaderComment(SkeletonContext context, StringBuilder sb) { + if (!context.getSettings().isWithComments()) { + return; + } + + final String title = I18N.getString("skeleton.window.title", context.getDocumentName()); + sb.append("# ").append(title).append(NL); //NOI18N + } + + + void appendClass(SkeletonContext context, StringBuilder sb) { + + String controllerClassName = makeClassName(context); + + sb.append("class ").append(controllerClassName); //NOI18N + + sb.append(NL); + sb.append(INDENT).append("include JRubyFX::Controller").append(NL).append(NL); //NOI18N + + appendImports(context, sb); + + if (context.getSettings().isWithComments()) { + sb.append(INDENT).append("# Marks this class as being a controller for the given fxml document").append(NL); //NOI18N + sb.append(INDENT).append("# This creates @instance_variables for all fx:id").append(NL); //NOI18N + } + String documentName = context.getDocumentName(); + if (!documentName.contains(".fxml")) { + documentName += ".fxml"; + } + sb.append(INDENT).append("fxml '").append(documentName).append("'").append(NL).append(NL); //NOI18N + + + if (context.getSettings().isWithComments()) { + sb.append(INDENT).append("# These @instance_variables will be injected by FXMLLoader & JRubyFX").append(NL); //NOI18N + } + + appendFieldsWithFxId(context, sb); + + appendFieldsResourcesAndLocation(context, sb); + + appendInitialize(context, sb); + + appendEventHandlers(context, sb); + + sb.append("end").append(NL); //NOI18N + } + + private String makeClassName(SkeletonContext context) { + String controllerClassName = "PleaseProvideControllerClassName"; + + if (hasController(context)) { + controllerClassName = getControllerClassName(context); + } + return controllerClassName; + } + + + private boolean hasController(SkeletonContext context) { + return context.getFxController() != null && !context.getFxController().isEmpty(); + } + + private String getControllerClassName(SkeletonContext context) { + String simpleName = context.getFxController().replace("$", "."); //NOI18N + int dot = simpleName.lastIndexOf('.'); + if (dot > -1) { + simpleName = simpleName.substring(dot + 1); + } + return simpleName; + } + + void appendFieldParameters(StringBuilder sb, Class fieldClazz) { + final TypeVariable>[] parameters = fieldClazz.getTypeParameters(); + if (parameters.length > 0) { + sb.append("<"); //NOI18N + String sep = ""; //NOI18N + for (TypeVariable ignored : parameters) { + sb.append(sep); + sb.append("?"); //NOI18N + sep = ", "; //NOI18N + } + sb.append(">"); //NOI18N + } + } + + + void appendFieldsResourcesAndLocation(SkeletonContext context, StringBuilder sb) { + if (!context.getSettings().isFull()) { + return; + } + + // these aren't built into JRubyFX's fxml_helper.rb, so just manually add the fields for reification + if (context.getSettings().isWithComments()) { + sb.append(INDENT).append("# ResourceBundle that was given to the FXMLLoader. Access as self.resources, or @resources if instance_variable is true").append(NL); //NOI18N + } + sb.append(INDENT); + sb.append("java_field '@javafx.fxml.FXML java.util.ResourceBundle resources', instance_variable: true"); + + if (context.getSettings().isWithComments()) { + sb.append(NL).append(NL).append(INDENT).append("# URL location of the FXML file that was given to the FXMLLoader. Access as self.location, or @location if instance_variable is true"); //NOI18N + } + sb.append(NL).append(INDENT); + sb.append("java_field '@javafx.fxml.FXML java.net.URL location', instance_variable: true"); + sb.append(NL).append(NL); + } + + + void appendFieldsWithFxId(SkeletonContext context, StringBuilder sb) { + for (Map.Entry> variable : context.getVariables().entrySet()) { + sb.append(INDENT).append("# @").append(variable.getKey()).append(": \t").append(variable.getValue().getSimpleName()); //NOI18N + appendFieldParameters(sb, variable.getValue()); // just for reference + sb.append(NL); + } + sb.append(NL); + } + + void appendInitialize(SkeletonContext context, StringBuilder sb) { + if (!context.getSettings().isFull()) { + return; + } + if (context.getSettings().isWithComments()) { + sb.append(INDENT).append("# Called by JRubyFX after FXML loading is complete. Different from Java, same as normal Ruby"); //NOI18N + sb.append(NL); + } + + sb.append(INDENT); + sb.append("def initialize()"); //NOI18N + sb.append(NL); + appendAssertions(context, sb); + sb.append(NL); + sb.append(INDENT); + sb.append("end").append(NL).append(NL); //NOI18N + } + + void appendEventHandlers(SkeletonContext context, StringBuilder sb) { + for (Map.Entry entry : context.getEventHandlers().entrySet()) { + String methodName = entry.getKey(); + String eventClassName = entry.getValue(); + + final String methodNamePured = methodName.replace("#", ""); //NOI18N + + sb.append(INDENT); + appendEventHandler(methodNamePured, eventClassName, sb); + sb.append(NL).append(NL); + } + } + + void appendEventHandler(String methodName, String eventClassName, StringBuilder sb) { + sb.append("def "); //NOI18N + sb.append(methodName); + sb.append("(").append("event) # event: ").append(eventClassName).append(NL).append(NL); //NOI18N + sb.append(INDENT).append("end"); //NOI18N + } + + void appendAssertions(SkeletonContext context, StringBuilder sb) { + for (String assertion : context.getAssertions()) { + sb.append(INDENT).append(INDENT) + .append("raise 'fx:id=\"").append(assertion).append("\" was not injected: check your FXML file ") //NOI18N + .append("\"").append(context.getDocumentName()).append("\".' if ") //NOI18N + .append("@").append(assertion).append(".nil?").append(NL); //NOI18N + } + } + +} diff --git a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonFileNameProposal.java b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonFileNameProposal.java index bd6657577..2e622085e 100644 --- a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonFileNameProposal.java +++ b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonFileNameProposal.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Gluon and/or its affiliates. + * Copyright (c) 2021, 2023, Gluon and/or its affiliates. * All rights reserved. Use is subject to license terms. * * This file is available and licensed under the following license: @@ -120,6 +120,9 @@ private File adjustToSrcMainDirWhenPossible(File controllerAtFxmlLocation) { case KOTLIN: location = location.replace(resources, kotlin); break; + case JRUBY: + // use default location in "resources" + break; } } } diff --git a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonSettings.java b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonSettings.java index a6c859d9c..17a5f2cd8 100644 --- a/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonSettings.java +++ b/kit/src/main/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonSettings.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Gluon and/or its affiliates. + * Copyright (c) 2021, 2023, Gluon and/or its affiliates. * All rights reserved. Use is subject to license terms. * * This file is available and licensed under the following license: @@ -38,7 +38,7 @@ class SkeletonSettings { private FORMAT_TYPE textFormat = FORMAT_TYPE.COMPACT; enum LANGUAGE { - JAVA("Java", ".java"), KOTLIN("Kotlin", ".kt"); + JAVA("Java", ".java"), KOTLIN("Kotlin", ".kt"), JRUBY("JRuby", ".rb"); private final String name; private final String ext; diff --git a/kit/src/test/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonBufferJRubyTest.java b/kit/src/test/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonBufferJRubyTest.java new file mode 100644 index 000000000..ec6fbd09f --- /dev/null +++ b/kit/src/test/java/com/oracle/javafx/scenebuilder/kit/skeleton/SkeletonBufferJRubyTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2023, Gluon and/or its affiliates. + * All rights reserved. Use is subject to license terms. + * + * This file is available and licensed under the following license: + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * - 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. + * - Neither the name of Oracle Corporation and Gluon nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * 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 + * OWNER 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. + */ +package com.oracle.javafx.scenebuilder.kit.skeleton; + +import com.oracle.javafx.scenebuilder.kit.JfxInitializer; +import com.oracle.javafx.scenebuilder.kit.editor.EditorController; +import com.oracle.javafx.scenebuilder.kit.fxom.FXOMDocument; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.File; +import java.io.IOException; +import java.net.URL; +import java.nio.file.Files; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; + +public class SkeletonBufferJRubyTest { + + @BeforeAll + public static void initialize() { + JfxInitializer.initialize(); + } + + @Test + public void skeletonToString_nestedTestFxml() throws IOException { + // given + SkeletonBuffer skeletonBuffer = load("TestNested.fxml"); + + // when + String skeleton = skeletonBuffer.toString(); + + // then + assertEqualsFileContent("skeleton_ruby_nested.txt", skeleton); + } + + @Test + public void skeletonToString_testFxml_full_withComments() throws IOException { + // given + SkeletonBuffer skeletonBuffer = load("Test.fxml"); + skeletonBuffer.setFormat(SkeletonSettings.FORMAT_TYPE.FULL); + skeletonBuffer.setTextType(SkeletonSettings.TEXT_TYPE.WITH_COMMENTS); + + // when + String skeleton = skeletonBuffer.toString(); + + // then + assertEqualsFileContent("skeleton_ruby_full_comments.txt", skeleton); + } + + @Test + public void skeletonToString_testFxml_withComments() throws IOException { + // given + SkeletonBuffer skeletonBuffer = load("Test.fxml"); + skeletonBuffer.setTextType(SkeletonSettings.TEXT_TYPE.WITH_COMMENTS); + + // when + String skeleton = skeletonBuffer.toString(); + + // then + assertEqualsFileContent("skeleton_ruby_comments.txt", skeleton); + } + + @Test + public void skeletonToString_testFxml_fullFormat() throws IOException { + // given + SkeletonBuffer skeletonBuffer = load("Test.fxml"); + skeletonBuffer.setFormat(SkeletonSettings.FORMAT_TYPE.FULL); + + // when + String skeleton = skeletonBuffer.toString(); + + // then + assertEqualsFileContent("skeleton_ruby_full.txt", skeleton); + } + + private void assertEqualsFileContent(String fileName, String actual) { + URL url = this.getClass().getResource(fileName); + File file = new File(url.getFile()); + + try { + String expectedFileContent = Files.readString(file.toPath()); + assertEquals(expectedFileContent, actual); + } catch (IOException e) { + fail("Unable to open file: " + fileName); + } + } + + private SkeletonBuffer load(String fxmlFile) throws IOException { + EditorController editorController = new EditorController(); + final URL fxmlURL = SkeletonBufferJRubyTest.class.getResource(fxmlFile); + final String fxmlText = FXOMDocument.readContentFromURL(fxmlURL); + editorController.setFxmlTextAndLocation(fxmlText, fxmlURL, false); + + SkeletonBuffer skeletonBuffer = new SkeletonBuffer(editorController.getFxomDocument(), "test"); + skeletonBuffer.setLanguage(SkeletonSettings.LANGUAGE.JRUBY); + return skeletonBuffer; + } +} diff --git a/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_comments.txt b/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_comments.txt new file mode 100644 index 000000000..4ca1818c1 --- /dev/null +++ b/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_comments.txt @@ -0,0 +1,17 @@ +# Sample Skeleton for 'test' Controller Class +class EmptyController + include JRubyFX::Controller + + # Marks this class as being a controller for the given fxml document + # This creates @instance_variables for all fx:id + fxml 'test.fxml' + + # These @instance_variables will be injected by FXMLLoader & JRubyFX + # @myTableView: TableView + # @myVbox: VBox + + def onMyVboxMouseEntered(event) # event: MouseEvent + + end + +end diff --git a/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_full.txt b/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_full.txt new file mode 100644 index 000000000..4eed9713c --- /dev/null +++ b/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_full.txt @@ -0,0 +1,25 @@ +class EmptyController + include JRubyFX::Controller + + # java_import 'java.net.URL' + # java_import 'java.util.ResourceBundle' + + fxml 'test.fxml' + + # @myTableView: TableView + # @myVbox: VBox + + java_field '@javafx.fxml.FXML java.util.ResourceBundle resources', instance_variable: true + java_field '@javafx.fxml.FXML java.net.URL location', instance_variable: true + + def initialize() + raise 'fx:id="myTableView" was not injected: check your FXML file "test".' if @myTableView.nil? + raise 'fx:id="myVbox" was not injected: check your FXML file "test".' if @myVbox.nil? + + end + + def onMyVboxMouseEntered(event) # event: MouseEvent + + end + +end diff --git a/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_full_comments.txt b/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_full_comments.txt new file mode 100644 index 000000000..784874f11 --- /dev/null +++ b/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_full_comments.txt @@ -0,0 +1,33 @@ +# Sample Skeleton for 'test' Controller Class +class EmptyController + include JRubyFX::Controller + + # java_import 'java.net.URL' + # java_import 'java.util.ResourceBundle' + + # Marks this class as being a controller for the given fxml document + # This creates @instance_variables for all fx:id + fxml 'test.fxml' + + # These @instance_variables will be injected by FXMLLoader & JRubyFX + # @myTableView: TableView + # @myVbox: VBox + + # ResourceBundle that was given to the FXMLLoader. Access as self.resources, or @resources if instance_variable is true + java_field '@javafx.fxml.FXML java.util.ResourceBundle resources', instance_variable: true + + # URL location of the FXML file that was given to the FXMLLoader. Access as self.location, or @location if instance_variable is true + java_field '@javafx.fxml.FXML java.net.URL location', instance_variable: true + + # Called by JRubyFX after FXML loading is complete. Different from Java, same as normal Ruby + def initialize() + raise 'fx:id="myTableView" was not injected: check your FXML file "test".' if @myTableView.nil? + raise 'fx:id="myVbox" was not injected: check your FXML file "test".' if @myVbox.nil? + + end + + def onMyVboxMouseEntered(event) # event: MouseEvent + + end + +end diff --git a/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_nested.txt b/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_nested.txt new file mode 100644 index 000000000..99390ad9f --- /dev/null +++ b/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/skeleton_ruby_nested.txt @@ -0,0 +1,13 @@ +class InnerController + include JRubyFX::Controller + + fxml 'test.fxml' + + # @myTableView: TableView + # @myVbox: VBox + + def onMyVboxMouseEntered(event) # event: MouseEvent + + end + +end