From 1531dc0cb1f385a87948f98a841d22ae218b4895 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?St=C3=A9phane=20Dervaux?= <stephane.dervaux@inrae.fr>
Date: Tue, 2 Jan 2024 14:02:51 +0100
Subject: [PATCH] Add a new static method in UITools to create the FXMLLoader
 and ckeck (and fix) the ContextClassLoader (null if on the AppKit Thread
 macOS)

---
 .../java/fr/inra/po2vocabmanager/MainApp.java | 24 ++----
 .../inra/po2vocabmanager/utils/UITools.java   | 11 +++
 .../view/dataView/DataOverviewController.java | 15 ++--
 .../ObservationOverviewController.java        | 76 +------------------
 .../dataView/ProjectOverviewController.java   |  6 +-
 .../view/dataView/StepOverviewController.java |  9 +--
 6 files changed, 30 insertions(+), 111 deletions(-)

diff --git a/src/main/java/fr/inra/po2vocabmanager/MainApp.java b/src/main/java/fr/inra/po2vocabmanager/MainApp.java
index accce8e3..d3bcff21 100644
--- a/src/main/java/fr/inra/po2vocabmanager/MainApp.java
+++ b/src/main/java/fr/inra/po2vocabmanager/MainApp.java
@@ -223,8 +223,7 @@ public class MainApp extends Application implements Launcher  {
             title.bind(Bindings.when(fileName.isEqualTo("")).then(appName).otherwise(Bindings.concat(appName).concat(" - ").concat(fileName).concat(" - V ").concat(version)));
             primaryStage.titleProperty().bind(Bindings.when(modified).then(title.concat(" *")).otherwise(title));
             try {
-                FXMLLoader loader = new FXMLLoader(MainApp.class.getResource("view/Splash.fxml"));
-//            loader.setLocation();
+                FXMLLoader loader = UITools.getFXMLLoader("view/Splash.fxml");
                 StackPane SplashLayout = (StackPane) loader.load();
                 SplashController c = loader.getController();
 
@@ -660,8 +659,7 @@ public class MainApp extends Application implements Launcher  {
 
             MainApp.mainApp = this;
             // Load root layout from fxml file.
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/RootLayout.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/RootLayout.fxml");
             rootLayout = (BorderPane) loader.load();
             rootLayoutController = loader.getController();
             rootLayoutController.setMainApp(this);
@@ -754,8 +752,7 @@ public class MainApp extends Application implements Launcher  {
     public void showChoiceOverview() {
         try {
             // Load person overview.
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/ChoiceManager.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/ChoiceManager.fxml");
             BorderPane choiceOverview = (BorderPane) loader.load();
 
             // Set person overview into the center of root layout.
@@ -797,8 +794,7 @@ public class MainApp extends Application implements Launcher  {
 
     public void initDataOverview() {
         try {
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/dataView/DataOverview.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/dataView/DataOverview.fxml");
             dataOverview = (AnchorPane) loader.load();
             dataControler = loader.getController();
             dataControler.setMainApp(this);
@@ -813,8 +809,7 @@ public class MainApp extends Application implements Launcher  {
     public void initOntologyOverview() {
         try {
             // Load person overview.
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/ontoView/OntologyOverview.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/ontoView/OntologyOverview.fxml");
             ontologyOverview = (AnchorPane) loader.load();
 
             // Give the controller access to the main app.
@@ -857,8 +852,7 @@ public class MainApp extends Application implements Launcher  {
     }
     public void showDeleteNodeOverview(VocabConcept node) {
         try {
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/ontoView/DeleteNodeOverview.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/ontoView/DeleteNodeOverview.fxml");
             BorderPane deleteNodeOverview = (BorderPane) loader.load();
 
             Stage modelStage = new Stage();
@@ -895,8 +889,7 @@ public class MainApp extends Application implements Launcher  {
     public void showSearchView() {
         try {
             // Load person overview.
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/ontoView/SearchOverview.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/ontoView/SearchOverview.fxml");
             BorderPane searchOverview = (BorderPane) loader.load();
 
             Stage modelStage = new Stage();
@@ -1344,8 +1337,7 @@ public class MainApp extends Application implements Launcher  {
     }
 
     public void importQUDT(VocabConcept item) {
-        FXMLLoader loader = new FXMLLoader();
-        loader.setLocation(MainApp.class.getResource("view/ontoView/QudtImport.fxml"));
+        FXMLLoader loader = UITools.getFXMLLoader("view/ontoView/QudtImport.fxml");
         BorderPane qudtImportOverview = null;
         try {
             qudtImportOverview = (BorderPane) loader.load();
diff --git a/src/main/java/fr/inra/po2vocabmanager/utils/UITools.java b/src/main/java/fr/inra/po2vocabmanager/utils/UITools.java
index e538a034..90c94900 100644
--- a/src/main/java/fr/inra/po2vocabmanager/utils/UITools.java
+++ b/src/main/java/fr/inra/po2vocabmanager/utils/UITools.java
@@ -47,6 +47,7 @@ import javafx.collections.transformation.FilteredList;
 import javafx.concurrent.Task;
 import javafx.event.ActionEvent;
 import javafx.event.EventHandler;
+import javafx.fxml.FXMLLoader;
 import javafx.geometry.HPos;
 import javafx.geometry.Insets;
 import javafx.geometry.Orientation;
@@ -185,6 +186,16 @@ public class UITools {
         return ab;
     }
 
+    public static FXMLLoader getFXMLLoader(String resource) {
+        // first checking for contextclassLoader (macos bug if Thread is AppKit Thread)
+        if (Thread.currentThread().getContextClassLoader() == null) {
+            Thread.currentThread().setContextClassLoader(UITools.class.getClassLoader());
+        }
+        FXMLLoader loader = new FXMLLoader();
+        loader.setLocation(MainApp.class.getResource(resource));
+        return loader;
+    }
+
     public static ObservableValue<ImageView> getFlag(String lang) {
 
         Image i;
diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/DataOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/DataOverviewController.java
index 66a48362..0b848f65 100644
--- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/DataOverviewController.java
+++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/DataOverviewController.java
@@ -101,8 +101,7 @@ public class DataOverviewController {
 
     public void initProcessOverview() {
         try {
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/dataView/ProcessOverview.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/dataView/ProcessOverview.fxml");
             processOverview = loader.load();
             AnchorPane.setTopAnchor(processOverview, 10.0);
             AnchorPane.setLeftAnchor(processOverview, 10.0);
@@ -117,8 +116,7 @@ public class DataOverviewController {
 
     public void initStepOverview() {
         try {
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/dataView/StepOverview.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/dataView/StepOverview.fxml");
             stepOverview = loader.load();
             AnchorPane.setTopAnchor(stepOverview, 10.0);
             AnchorPane.setLeftAnchor(stepOverview, 10.0);
@@ -133,8 +131,7 @@ public class DataOverviewController {
 
     public void initObservationOverview() {
         try {
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/dataView/ObservationOverview.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/dataView/ObservationOverview.fxml");
             observationOverview = loader.load();
             AnchorPane.setTopAnchor(observationOverview, 10.0);
             AnchorPane.setLeftAnchor(observationOverview, 10.0);
@@ -149,8 +146,7 @@ public class DataOverviewController {
 
     public void initItineraryOverview() {
         try {
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/dataView/ItineraryOverview.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/dataView/ItineraryOverview.fxml");
             itineraryOverview = loader.load();
             AnchorPane.setTopAnchor(itineraryOverview, 10.0);
             AnchorPane.setLeftAnchor(itineraryOverview, 10.0);
@@ -165,8 +161,7 @@ public class DataOverviewController {
 
     public void initProjectOverview() {
         try {
-            FXMLLoader loader = new FXMLLoader();
-            loader.setLocation(MainApp.class.getResource("view/dataView/ProjectOverview.fxml"));
+            FXMLLoader loader = UITools.getFXMLLoader("view/dataView/ProjectOverview.fxml");
             projectOverview = loader.load();
             AnchorPane.setTopAnchor(projectOverview, 10.0);
             AnchorPane.setLeftAnchor(projectOverview, 10.0);
diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/ObservationOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/ObservationOverviewController.java
index bd7535e2..4cdcdda5 100644
--- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/ObservationOverviewController.java
+++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/ObservationOverviewController.java
@@ -239,8 +239,7 @@ public class ObservationOverviewController {
         VBox.setVgrow(matMetPane, Priority.ALWAYS);
         matMetPane.setText("Materials & Methods");
         matMetPane.setMinWidth(Double.NEGATIVE_INFINITY);
-        FXMLLoader loaderMatMet = new FXMLLoader();
-        loaderMatMet.setLocation(MainApp.class.getResource("view/dataView/MaterialMethodLinkOverview.fxml"));
+        FXMLLoader loaderMatMet = UITools.getFXMLLoader("view/dataView/MaterialMethodLinkOverview.fxml");
         SplitPane matmetOverview = null;
         try {
             matmetOverview = loaderMatMet.load();
@@ -334,82 +333,9 @@ public class ObservationOverviewController {
             HBox.setHgrow(emptyLabel, Priority.ALWAYS);
             bb.setPadding(new Insets(0,3,0,0));
             bb.minWidthProperty().bind(tablePane.widthProperty().subtract(25));
-//            b.setRight(delTable);
-//            b.getChildren().add(delTable);
-//            HBox.setHgrow(delTable, Priority.ALWAYS);
-//            GridPane.setHgrow(delTable, Priority.ALWAYS);
-
             tablePane.setGraphic(bb);
         }
 
-//        StepFile f = (StepFile) node.getFile();
-//        f.bindTitle(stepTitle);
-//        boxContent.getChildren().retainAll(stepPanel);
-//
-//        CompositionFile compoFile = f.getCompositionFile();
-//        ConduiteFile condFile = f.getConduiteFile();
-//
-//        TitledPane mixturePane = new TitledPane();
-//        mixturePane.setText("Mixture");
-//        TabPane compoTabPane = new TabPane();
-//
-//
-//        Tab tabCompo = new Tab("Composition");
-//        BorderPane bc = new BorderPane();
-//
-//        FXMLLoader loadercompo = new FXMLLoader();
-//        loadercompo.setLocation(MainApp.class.getResource("view/dataView/MaterialMethodOverview.fxml"));
-//        BorderPane matmetCompoOverview = null;
-//        try {
-//            matmetCompoOverview = (BorderPane) loadercompo.load();
-//        } catch (IOException e) {
-//            e.printStackTrace();
-//        }
-//        MaterialMethodOverviewController matmetCompoController = loadercompo.getController();
-//        matmetCompoOverview.setPrefHeight(130);
-//        bc.setTop(matmetCompoOverview);
-//
-//
-//        TableView compoTable = new TableView();
-//        tabCompo.setContent(bc);
-//        bc.setCenter(compoTable);
-//        compoTabPane.getTabs().add(tabCompo);
-//
-//        if(compoFile != null) {
-//            // on ajoute les consignes
-//            matmetCompoController.setListConsign(compoFile.getListConsign());
-//            matmetCompoController.showItem(compoFile.getMaterialMethodPart());
-//            compoFile.bindData(compoTable);
-//        }
-//
-//        Tab tabConduite = new Tab("Conduite");
-//        BorderPane bco = new BorderPane();
-//        FXMLLoader loadercond = new FXMLLoader();
-//        loadercond.setLocation(MainApp.class.getResource("view/dataView/MaterialMethodOverview.fxml"));
-//        BorderPane matmetCondOverview = null;
-//        try {
-//            matmetCondOverview = (BorderPane) loadercond.load();
-//        } catch (IOException e) {
-//            e.printStackTrace();
-//        }
-//        MaterialMethodOverviewController matmetCondController = loadercond.getController();
-//        matmetCondOverview.setPrefHeight(130);
-//        bco.setTop(matmetCondOverview);
-//
-//        TableView condTable = new TableView();
-//        tabConduite.setContent(bco);
-//        bco.setCenter(condTable);
-//        compoTabPane.getTabs().add(tabConduite);
-//        if(condFile != null) {
-//            matmetCondController.setListConsign(condFile.getListConsign());
-//            matmetCondController.showItem(condFile.getMaterialMethodPart());
-//            condFile.bindData(condTable);
-//        }
-//
-//        mixturePane.setContent(compoTabPane);
-//        VBox.setVgrow(mixturePane, Priority.ALWAYS);
-//        boxContent.getChildren().add(mixturePane);
-//
     }
 
     public void unloadControler() {
diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/ProjectOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/ProjectOverviewController.java
index 9541698c..09fdc2d4 100644
--- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/ProjectOverviewController.java
+++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/ProjectOverviewController.java
@@ -115,16 +115,14 @@ public class ProjectOverviewController {
 
         Data data = this.mainApp.getDataControler().getCurrentData();
         try {
-            FXMLLoader loaderMaterial = new FXMLLoader();
-            loaderMaterial.setLocation(MainApp.class.getResource("view/dataView/MaterialMethodOverview.fxml"));
+            FXMLLoader loaderMaterial = UITools.getFXMLLoader("view/dataView/MaterialMethodOverview.fxml");
             SplitPane materialOverview = (SplitPane) loaderMaterial.load();
             MaterialMethodOverviewController materialController = loaderMaterial.getController();
             materialController.setMainApp(this.mainApp, DataPartType.MATERIAL_RAW);
             materialController.showItem(data.getMaterialMethodFile().getMaterialPart());
             paneMaterial.setContent(materialOverview);
 
-            FXMLLoader loaderMethod = new FXMLLoader();
-            loaderMethod.setLocation(MainApp.class.getResource("view/dataView/MaterialMethodOverview.fxml"));
+            FXMLLoader loaderMethod = UITools.getFXMLLoader("view/dataView/MaterialMethodOverview.fxml");
             SplitPane methodOverview = (SplitPane) loaderMethod.load();
             MaterialMethodOverviewController methodController = loaderMethod.getController();
             methodController.setMainApp(this.mainApp, DataPartType.METHOD_RAW);
diff --git a/src/main/java/fr/inra/po2vocabmanager/view/dataView/StepOverviewController.java b/src/main/java/fr/inra/po2vocabmanager/view/dataView/StepOverviewController.java
index 49f28777..2c8dd5a4 100644
--- a/src/main/java/fr/inra/po2vocabmanager/view/dataView/StepOverviewController.java
+++ b/src/main/java/fr/inra/po2vocabmanager/view/dataView/StepOverviewController.java
@@ -150,8 +150,7 @@ public class StepOverviewController {
         VBox.setVgrow(matMetPane, Priority.ALWAYS);
         matMetPane.setText("Materials & Methods");
         matMetPane.setMinWidth(Double.NEGATIVE_INFINITY);
-        FXMLLoader loaderMatMet = new FXMLLoader();
-        loaderMatMet.setLocation(MainApp.class.getResource("view/dataView/MaterialMethodLinkOverview.fxml"));
+        FXMLLoader loaderMatMet = UITools.getFXMLLoader("view/dataView/MaterialMethodLinkOverview.fxml");
         SplitPane matmetOverview = null;
         try {
             matmetOverview = (SplitPane) loaderMatMet.load();
@@ -251,8 +250,7 @@ public class StepOverviewController {
             Tab tabCompo = new Tab("Composition");
             tabCompo.setClosable(false);
             BorderPane bc = new BorderPane();
-            FXMLLoader loadercompo = new FXMLLoader();
-            loadercompo.setLocation(MainApp.class.getResource("view/dataView/MaterialMethodLinkOverview.fxml"));
+            FXMLLoader loadercompo = UITools.getFXMLLoader("view/dataView/MaterialMethodLinkOverview.fxml");
             SplitPane matmetCompoOverview = null;
             try {
                 matmetCompoOverview = (SplitPane) loadercompo.load();
@@ -282,8 +280,7 @@ public class StepOverviewController {
             Tab tabConduite = new Tab("Guideline");
             tabConduite.setClosable(false);
             BorderPane bco = new BorderPane();
-            FXMLLoader loadercond = new FXMLLoader();
-            loadercond.setLocation(MainApp.class.getResource("view/dataView/MaterialMethodLinkOverview.fxml"));
+            FXMLLoader loadercond = UITools.getFXMLLoader("view/dataView/MaterialMethodLinkOverview.fxml");
             SplitPane matmetCondOverview = null;
             try {
                 matmetCondOverview = (SplitPane) loadercond.load();
-- 
GitLab