Skip to content

Comments

fix: adds <fx:include> elements to controller skeleton when a fxid is assigned (#811)#841

Open
Oliver-Loeffler wants to merge 6 commits intogluonhq:masterfrom
Oliver-Loeffler:issue-811
Open

fix: adds <fx:include> elements to controller skeleton when a fxid is assigned (#811)#841
Oliver-Loeffler wants to merge 6 commits intogluonhq:masterfrom
Oliver-Loeffler:issue-811

Conversation

@Oliver-Loeffler
Copy link
Collaborator

This PR introduces code which enables Scene Builder to declare references to <fx:include> elements which have a fx:id assigned in the controller skeleton. It uses the fx:id defined in the outer FXML file but the type of the node declared as root in the inner FXML file.

Issue

Fixes #811

Progress

…assigned, are now added to the controller skeleton. (gluonhq#811)
@Oliver-Loeffler Oliver-Loeffler changed the title fix: Reference fields for <fx:include> elements, which have a 'fxid' … fix: adds <fx:include> elements to controller skeleton when a fxid is assigned (#811) Oct 2, 2025
…com.oracle.javafx.scenebuilder.kit.skeleton to ALL-UNNAMED to enable testing.
@Oliver-Loeffler Oliver-Loeffler requested review from abhinayagarwal and removed request for abhinayagarwal October 2, 2025 19:10
Copy link
Collaborator

@jperedadnr jperedadnr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work!
I added two minor comments, and possibly some follow-ups:

The skeleton shows classes from private packages instead of public ones:

image

(it should be import javafx.collections.FXCollections instead of import com.sun.javafx.collections.ObservableListWrapper)

And when trying to edit the included file from the Hierarchy context menu:

image

I get this error:

com.oracle.javafx.scenebuilder.kit.editor.FileBrowserRevealException: The command to reval the file exited with an error (exitValue=1).
Command: open /Users/user/SceneBuilder/kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/fxinclude_with_fxid_inner.fxml
Working Dir: null
	at com.gluonhq.scenebuilder.kit@25.0.0-SNAPSHOT/com.oracle.javafx.scenebuilder.kit.editor.EditorPlatform.executeDaemon(EditorPlatform.java:339)
	at com.gluonhq.scenebuilder.kit@25.0.0-SNAPSHOT/com.oracle.javafx.scenebuilder.kit.editor.EditorPlatform.open(EditorPlatform.java:242)
	at com.gluonhq.scenebuilder.kit@25.0.0-SNAPSHOT/com.oracle.javafx.scenebuilder.kit.editor.EditorController.performEditIncludedFile(EditorController.java:2283)
	at com.gluonhq.scenebuilder.kit@25.0.0-SNAPSHOT/com.oracle.javafx.scenebuilder.kit.editor.EditorController.performControlAction(EditorController.java:1522)
	at com.gluonhq.scenebuilder.kit@25.0.0-SNAPSHOT/com.oracle.javafx.scenebuilder.kit.editor.util.ContextMenuController$ControlActionController.perform(ContextMenuController.java:568)
...

@Oliver-Loeffler Oliver-Loeffler force-pushed the issue-811 branch 2 times, most recently from 88d95b8 to a09948e Compare October 14, 2025 21:44
@Oliver-Loeffler
Copy link
Collaborator Author

Oliver-Loeffler commented Oct 14, 2025

I've reworked the type detection for the controller skeleton. Instead of the ObservableListWrapper, there is now the reference to the nearest JavaFX related interface, which is javafx.collections.ObservableList. The editing should also now work (have not tested on MacOS or Linux yet). On Windows it works, regardless if the working dir is provided or not.

Ideally, this would open in SceneBuilder as a document, but this is much more complex hence I propose we make this work in a separate issue. Would you file an issue for that @jperedadnr ?

image

The FXML code forces the loader to create an ObservableList.

<FXCollections fx:id="myItems" fx:factory="observableArrayList">
    <String fx:value="1" />
    <String fx:value="20" />
    <String fx:value="300" />
</FXCollections>

The corresponding FXCollections code shows, that the import should be javafx.collections.ObservableList (as it is now).

    /**
     * Creates a new observable array list with {@code items} added to it.
     * @param <E> The type of List to be wrapped
     * @param items the items that will be in the new observable ArrayList
     * @return a newly created observableArrayList
     * @see #observableArrayList()
     */
    public static <E> ObservableList<E> observableArrayList(E... items) {
        return observableList(new ArrayList<>(Arrays.asList(items)));
    }

Copy link
Collaborator

@jperedadnr jperedadnr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When I run SB with the changes from this PR, and open this file kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/fxinclude_with_fxid_outer.fxml, I see the skeleton controller as expected, good work!

However, if I select the FXML Pane node from the hierarchy, press right click, and select from the context menu Edit Included File, it doesn't work (nothing happens), and now I see this exception:

INFO: Successfully opened file /kit/src/test/resources/com/oracle/javafx/scenebuilder/kit/skeleton/fxinclude_with_fxid_outer.fxml
Nov 23, 2025 2:33:11 PM com.oracle.javafx.scenebuilder.app.SceneBuilderApp$SceneBuilderUncaughtExceptionHandler uncaughtException
SEVERE: An exception was thrown:
java.lang.IndexOutOfBoundsException: Index 0 out of bounds for length 0
        at java.base/jdk.internal.util.Preconditions.outOfBounds(Preconditions.java:100)
        at java.base/jdk.internal.util.Preconditions.outOfBoundsCheckIndex(Preconditions.java:106)
        at java.base/jdk.internal.util.Preconditions.checkIndex(Preconditions.java:302)
        at java.base/java.util.Objects.checkIndex(Objects.java:365)
        at java.base/java.util.ArrayList.get(ArrayList.java:428)
        at com.gluonhq.scenebuilder.app@25.0.0-SNAPSHOT/com.oracle.javafx.scenebuilder.app.SceneBuilderApp.handleOpenFilesAction(SceneBuilderApp.java:531)
        at com.gluonhq.scenebuilder.app@25.0.0-SNAPSHOT/com.oracle.javafx.scenebuilder.app.SceneBuilderApp.handleOpenFilesAction(SceneBuilderApp.java:512)
        at com.gluonhq.scenebuilder.app@25.0.0-SNAPSHOT/com.oracle.javafx.scenebuilder.app.AppPlatform$MessageBoxDelegate.lambda$messageBoxDidGetMessage$0(AppPlatform.java:203)
        at javafx.graphics@25/com.sun.javafx.application.PlatformImpl.lambda$runLater$0(PlatformImpl.java:424)
        at javafx.graphics@25/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)

I don't get to the error I mentioned in my previous review #841 (review), that seems fixed with your changes in EditorPlatform, but still nothing happens.

*/
class TypeLookup {

private String packageNamePrefix;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be final

return new TypeLookup("javafx.").findFirstPublicInterfaceOrSuperclass(source);
}

public Optional<Class<?>> findFirstPublicInterfaceOrSuperclass(Object obj) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be package-private (so it can be accessed by the test)

assertEquals(javafx.css.Styleable.class, result.get());
}

class CustomJavaFxType implements Styleable {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class can be static

* (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;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

II wonder if this should belong to com.oracle.javafx.scenebuilder.kit.util

<children>
<fx:include fx:id="includedPane" source="fxinclude_with_fxid_inner.fxml" />
<Label fx:id="myLabel" text="Label" />
<Label fx:id="myLabel" text="Label" />
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Duplicated line, remove


<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/23" xmlns:fx="http://javafx.com/fxml/1">
<children>
<HBox prefHeight="100.0" prefWidth="200.0">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The inner pane is too big, and pushes label and combo to the right
image

While this is totally fine for a test, if you want to play around with this, opening with SB, it is probably better to adjust it.
For instance, inner pane with pref size 100x50, and Box with pref size 100x400 gives

image

I added the red background to the inner panner just for testing, but I noticed an issue (for a follow up):
if you select the inner FXML Pane node from the hierarchy, the selection goes to its parent (the HBox) instead:

image

<Label fx:id="myLabel" text="Label" />
<ComboBox fx:id="descriptionFilter" editable="true" layoutX="226.0" layoutY="55.0" prefHeight="25.0" prefWidth="204.0" promptText="Series Description">
<items>
<FXCollections fx:id="myItems" fx:factory="observableArrayList">
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fix for the FXCollections works with TypeLookup, good work!

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

"Show Sample Controller Skeleton" fails when an include has an "fx:id".

2 participants