44import com .xwintop .xJavaFxTool .common .logback .ConsoleLogAppender ;
55import com .xwintop .xJavaFxTool .controller .IndexController ;
66import com .xwintop .xJavaFxTool .model .PluginJarInfo ;
7- import com .xwintop .xJavaFxTool .plugin .PluginLoader ;
7+ import com .xwintop .xJavaFxTool .plugin .PluginClassLoader ;
8+ import com .xwintop .xJavaFxTool .plugin .PluginContainer ;
89import com .xwintop .xJavaFxTool .utils .Config ;
910import com .xwintop .xcore .javafx .dialog .FxAlerts ;
11+ import com .xwintop .xcore .util .javafx .AlertUtil ;
1012import com .xwintop .xcore .util .javafx .JavaFxViewUtil ;
1113import javafx .event .ActionEvent ;
1214import javafx .event .Event ;
15+ import javafx .fxml .FXMLLoader ;
16+ import javafx .scene .Node ;
1317import javafx .scene .control .Tab ;
18+ import javafx .scene .control .TabPane ;
1419import javafx .scene .control .TextArea ;
20+ import javafx .scene .image .Image ;
21+ import javafx .scene .image .ImageView ;
22+ import javafx .scene .layout .BorderPane ;
23+ import javafx .scene .web .WebEngine ;
24+ import javafx .scene .web .WebView ;
1525import javafx .stage .Stage ;
1626import lombok .Data ;
1727import lombok .extern .slf4j .Slf4j ;
28+ import org .apache .commons .lang3 .StringUtils ;
1829
30+ import java .lang .ref .WeakReference ;
1931import java .util .HashMap ;
2032import java .util .Locale ;
2133import java .util .Map ;
@@ -37,7 +49,7 @@ public void setLanguageAction(String languageType) throws Exception {
3749 } else if ("English" .equals (languageType )) {
3850 Config .set (Config .Keys .Locale , Locale .US );
3951 }
40- FxAlerts . info ( "" , indexController .getBundle ().getString ("SetLanguageText" ));
52+ AlertUtil . showInfoAlert ( indexController .getBundle ().getString ("SetLanguageText" ));
4153 }
4254
4355 public void addNodepadAction (ActionEvent event ) {
@@ -100,9 +112,9 @@ public void loadPlugin(PluginJarInfo pluginJarInfo) {
100112 String controllerType = pluginJarInfo .getControllerType ();
101113
102114 if (controllerType .equals ("Node" )) {
103- tab = PluginLoader . loadIsolatedPluginAsTab (pluginJarInfo , indexController .getTabPaneMain (), indexController .getSingleWindowBootCheckMenuItem ().isSelected ());
115+ tab = loadIsolatedPluginAsTab (pluginJarInfo , indexController .getTabPaneMain (), indexController .getSingleWindowBootCheckMenuItem ().isSelected ());
104116 } else if (controllerType .equals ("WebView" )) {
105- tab = PluginLoader . loadWebViewAsTab (pluginJarInfo , indexController .getTabPaneMain (), indexController .getSingleWindowBootCheckMenuItem ().isSelected ());
117+ tab = loadWebViewAsTab (pluginJarInfo , indexController .getTabPaneMain (), indexController .getSingleWindowBootCheckMenuItem ().isSelected ());
106118 } else {
107119 throw new AppException ("找不到 controllerType=" + controllerType + " 的加载方式" );
108120 }
@@ -112,4 +124,91 @@ public void loadPlugin(PluginJarInfo pluginJarInfo) {
112124 jarInfoMap .put (pluginJarInfo , tab );
113125 }
114126 }
127+
128+ /**
129+ * 以新 Tab 方式打开插件,但使用独立的 ClassLoader
130+ */
131+ public static Tab loadIsolatedPluginAsTab (PluginJarInfo plugin , TabPane tabPane , boolean singleWindowBoot ) {
132+ try {
133+ PluginContainer pluginContainer = new PluginContainer (PluginClassLoader .class .getClassLoader (), plugin );
134+ WeakReference <PluginContainer > containerRef = new WeakReference <>(pluginContainer );
135+ FXMLLoader generatingCodeFXMLLoader = pluginContainer .createFXMLLoader ();
136+ if (generatingCodeFXMLLoader == null ) {
137+ return null ;
138+ }
139+
140+ if (singleWindowBoot ) {
141+ JavaFxViewUtil .getNewStage (plugin .getTitle (), plugin .getIconPath (), generatingCodeFXMLLoader );
142+ return null ;
143+ }
144+
145+ Tab tab = new Tab (plugin .getTitle ());
146+ if (StringUtils .isNotEmpty (plugin .getIconPath ())) {
147+ ImageView imageView = new ImageView (new Image (plugin .getIconPath ()));
148+ imageView .setFitHeight (18 );
149+ imageView .setFitWidth (18 );
150+ tab .setGraphic (imageView );
151+ }
152+
153+ Node root = generatingCodeFXMLLoader .load ();
154+ Object controller = generatingCodeFXMLLoader .getController ();
155+ WeakReference <Object > controllerRef = new WeakReference <>(controller );
156+
157+ tab .setContent (root );
158+ tabPane .getTabs ().add (tab );
159+ tabPane .getSelectionModel ().select (tab );
160+
161+ tab .setOnCloseRequest (
162+ event -> {
163+ Object ctrl = controllerRef .get ();
164+ if (ctrl != null ) {
165+ JavaFxViewUtil .setControllerOnCloseRequest (ctrl , event );
166+ }
167+
168+ PluginContainer container = containerRef .get ();
169+ if (container != null ) {
170+ log .info ("插件关闭:" + container .getPluginJarInfo ().getName ());
171+ container .unload ();
172+ }
173+ }
174+ );
175+
176+ return tab ;
177+ } catch (Exception e ) {
178+ log .error ("加载插件失败" , e );
179+ FxAlerts .error ("插件加载失败" , e );
180+ }
181+
182+ return null ;
183+ }
184+
185+ public static Tab loadWebViewAsTab (PluginJarInfo plugin , TabPane tabPane , boolean singleWindowBoot ) {
186+ WebView browser = new WebView ();
187+ WebEngine webEngine = browser .getEngine ();
188+ String url = plugin .getPagePath ();
189+ String title = plugin .getTitle ();
190+
191+ if (url .startsWith ("http" )) {
192+ webEngine .load (url );
193+ } else {
194+ PluginContainer pluginContainer = new PluginContainer (plugin );
195+ webEngine .load (pluginContainer .getResource (url ).toExternalForm ());
196+ }
197+
198+ if (singleWindowBoot ) {
199+ JavaFxViewUtil .getNewStage (title , plugin .getIconPath (), new BorderPane (browser ));
200+ return null ;
201+ }
202+ Tab tab = new Tab (title );
203+ if (StringUtils .isNotEmpty (plugin .getIconPath ())) {
204+ ImageView imageView = new ImageView (new Image (plugin .getIconPath ()));
205+ imageView .setFitHeight (18 );
206+ imageView .setFitWidth (18 );
207+ tab .setGraphic (imageView );
208+ }
209+ tab .setContent (browser );
210+ tabPane .getTabs ().add (tab );
211+ tabPane .getSelectionModel ().select (tab );
212+ return tab ;
213+ }
115214}
0 commit comments