package is.L42.connected.withHtml; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URISyntaxException; import java.net.URL; import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import facade.L42; import netscape.javascript.JSObject; import javafx.application.Application; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.concurrent.Worker.State; import javafx.concurrent.Worker; import javafx.scene.Scene; import javafx.scene.layout.StackPane; import javafx.scene.web.WebEngine; import javafx.scene.web.WebView; import javafx.stage.Stage; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; public class FrameFX { public static void open(String title,String content){ try{ openThrow(title,content); loadEventHandler(); } catch(IOException| InterruptedException e ){throw new Error(e);} } private static void openThrow(String _title,String _content) throws IOException, InterruptedException { title=_title; content =head+"<base href='"+L42.path.toUri()+"' />"+_content+"</html>"; System.out.println(content); synchronized(dumbLock){ laucherThread.start(); waitForCompletion();//of html loading } } private static void loadEventHandler() { synchronized(dumbLock){ Platform.runLater(() ->{ Object o=NestedPrivate.webEngine.executeScript("window.event42"); assert o instanceof JSObject : o.toString(); JSObject jsobj = (JSObject)o; FrameFX.eventCollector=new EventCollected(); jsobj.setMember("eventCollector",eventCollector ); NestedPrivate.webEngine.setOnAlert(event->{ Alert alert = new Alert(AlertType.INFORMATION); alert.setTitle("Information Dialog"); alert.setHeaderText(null); alert.setContentText(event.getData()); alert.showAndWait(); }); //<a href="" onclick="java.add('bla');">here</a> synchronized(dumbLock){dumbLock.notifyAll();} }); waitForCompletion(); } } public static void setId(String id,String body) { synchronized(dumbLock){ Platform.runLater(() ->setIdFx(id,body)); waitForCompletion(); } } private static void setIdFx(String id, String body) { body=body.replace("\"","\\\""); body=body.replace("\n","\\n"); String submitted="$(\"#"+id+"\").replaceWith( \""+body+"\" );"; //System.out.println(submitted); NestedPrivate.webEngine.executeScript(submitted); //executeScript *is syncronus* synchronized(dumbLock){dumbLock.notifyAll();} } @SuppressWarnings("serial") public static class ApplicationDead extends Exception{} public static String getEventString() throws ApplicationDead{ synchronized(eventCollector){ while(eventCollector.events.isEmpty()){ if(!laucherThread.isAlive()){throw new ApplicationDead();} try{eventCollector.wait(500);} catch (InterruptedException e) { Thread.currentThread().interrupt(); throw new Error(e); } } return eventCollector.events.remove(0); } } public static final Object dumbLock=new Object(); public static volatile String title; public static volatile String content; public static void waitForCompletion() { try{dumbLock.wait();} catch(InterruptedException e){ Thread.currentThread().interrupt(); throw new Error(e); } } public static class NestedPrivate extends Application { public NestedPrivate(){} @Override public void start(Stage primaryStage) { primaryStage.setTitle(title); primaryStage.setOnCloseRequest((boh)->Platform.exit()); load(content); StackPane root = new StackPane(); root.getChildren().add(wv); primaryStage.setScene(new Scene(root, 700, 700)); primaryStage.show(); } private WebView load(String content){ webEngine.loadContent(content); webEngine.getLoadWorker().stateProperty().addListener((ChangeListener<State>) (ObservableValue<? extends State> ov, State oldState, State newState)->{ if (newState == Worker.State.SUCCEEDED) { synchronized(dumbLock){dumbLock.notifyAll();} } }); return wv; } public static final WebView wv =new WebView(); public static final WebEngine webEngine = wv.getEngine(); } private static final String head; private static final Thread laucherThread=new Thread(){ public void run(){ Application.launch(NestedPrivate.class,new String[0]); synchronized(eventCollector){eventCollector.notifyAll();} } }; private static EventCollected eventCollector; static {try ( BufferedReader reader = new BufferedReader(new InputStreamReader(FrameFX.class.getResourceAsStream("header.html"))) ){ StringBuilder out = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { out.append(line); out.append("\n"); } head = out.toString(); } catch (IOException e) {throw new Error(e);} } public static class EventCollected { private final List<String>events=Collections.synchronizedList(new ArrayList<>()); public void add(String event) {//this happens in the FX thread synchronized(this){ events.add(event); this.notifyAll(); } //System.out.println(events); //System.out.println("*---------------"); } } public static String executeJs(String s1) { synchronized(dumbLock){ String[] res=new String[1];//stupid final limitations Platform.runLater(() ->{res[0]=executeJsFx(s1);}); waitForCompletion();//TODO:Do not work! return res[0]; } } private static String executeJsFx(String body) { body=body.replace("\"","\\\""); body=body.replace("\n","\\n"); //String submitted="$(\"#"+id+"\").replaceWith( \""+body+"\" );"; //System.out.println(submitted); String res=executeAndConvert(body); //executeScript *is syncronus* synchronized(dumbLock){dumbLock.notifyAll();} return res; } public static String executeAndConvert(String body) { try{ Object res=NestedPrivate.webEngine.executeScript(body); if(res ==null){return "";} if(res instanceof String){return (String)res;} if(res instanceof Integer){return res.toString();} if(res instanceof Double){return res.toString();} if(res instanceof Boolean){return res.toString();} //if(res instanceof netscape.javascript.JSObject){return "";} return ""; } catch(netscape.javascript.JSException jsExc){return ""+jsExc;} } }