package flow.netbeans.markdown.preview.ext; import flow.netbeans.markdown.preview.AbstractHtmlView; import javafx.application.Platform; import javafx.beans.value.ChangeListener; import javafx.beans.value.ObservableValue; import javafx.concurrent.Worker; import javafx.embed.swing.JFXPanel; import javafx.event.EventHandler; import javafx.scene.Scene; import javafx.scene.layout.BorderPane; import javafx.scene.web.WebEvent; import javafx.scene.web.WebView; import javafx.util.Callback; import javax.swing.JComponent; public class FXHtmlView extends AbstractHtmlView { private static final int PANEL_WIDTH_INT = 675; private static final int PANEL_HEIGHT_INT = 400; private final JFXPanel fxPanel; private WebView webView; private String currentContent = ""; public FXHtmlView() { fxPanel = new JFXPanel(); Platform.setImplicitExit(false); Platform.runLater(new Runnable() { @Override public void run() { createScene(); } }); } @Override public JComponent getComponent() { return fxPanel; } @Override public void setContent(final String content) { Platform.runLater(new Runnable() { @Override public void run() { currentContent = content; final Number x = (Number) webView.getEngine().executeScript("document.body.scrollLeft"); final Number y = (Number) webView.getEngine().executeScript("document.body.scrollTop"); webView.getEngine().loadContent(currentContent); final Worker<Void> loadWorker = webView.getEngine().getLoadWorker(); loadWorker.stateProperty().addListener(new ChangeListener<Worker.State>() { @Override public void changed(ObservableValue<? extends Worker.State> observable, Worker.State oldValue, Worker.State newValue) { switch (newValue) { case SUCCEEDED: loadWorker.stateProperty().removeListener(this); String script = String.format("window.scrollTo(%d,%d);", x, y); webView.getEngine().executeScript(script); break; case FAILED: case CANCELLED: loadWorker.stateProperty().removeListener(this); break; } } }); } }); } @Override public boolean isHtmlFullySupported() { return true; } private void createScene() { Double widthDouble = new Integer(PANEL_WIDTH_INT).doubleValue(); Double heightDouble = new Integer(PANEL_HEIGHT_INT).doubleValue(); webView = new WebView(); webView.setMinSize(widthDouble, heightDouble); webView.setPrefSize(widthDouble, heightDouble); webView.setContextMenuEnabled(false); webView.getEngine().setConfirmHandler(new Callback<String, Boolean>() { @Override public Boolean call(String p) { return false; } }); webView.getEngine().locationProperty().addListener(new ChangeListener<String>() { @Override public void changed(ObservableValue<? extends String> ov, String oldValue, String newValue) { if (!"".equals(newValue)) { Platform.runLater(new Runnable() { @Override public void run() { webView.getEngine().loadContent(currentContent); } }); showURLExternal(newValue); } } }); webView.getEngine().setOnStatusChanged(new EventHandler<WebEvent<String>>() { @Override public void handle(WebEvent<String> e) { setStatusMessage(e.getData()); } }); BorderPane pane = new BorderPane(); pane.setCenter(webView); Scene scene = new Scene(pane); fxPanel.setScene(scene); } }