extract JavaFxHtml panel into platform

This commit is contained in:
Ekaterina Tuzova
2018-06-18 16:41:09 +03:00
parent b59566b863
commit 63e9ac9936
2 changed files with 166 additions and 0 deletions
@@ -0,0 +1,53 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ui.javafx;
import com.intellij.util.FieldAccessor;
import com.intellij.util.ui.JBUI;
import com.intellij.util.ui.UIUtil;
import com.sun.javafx.embed.EmbeddedSceneInterface;
import com.sun.javafx.tk.TKScene;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import java.awt.*;
public class JFXPanelWrapper extends JFXPanel {
private static final FieldAccessor<JFXPanel, Integer> myScaleFactorAccessor = new FieldAccessor<>(JFXPanel.class, "scaleFactor");
public JFXPanelWrapper() {
Platform.setImplicitExit(false);
}
/**
* This override fixes the situation of using multiple JFXPanels
* with jbtabs/splitters when some of them are not showing.
* On getMinimumSize there is no layout manager nor peer so
* the result could be #size() which is incorrect.
* @return zero size
*/
@Override
public Dimension getMinimumSize() {
return new Dimension(0, 0);
}
@Override
public void addNotify() {
super.addNotify();
if (UIUtil.isJreHiDPIEnabled()) {
// JFXPanel is scaled asynchronously after first repaint, what may lead
// to showing unscaled content. To work it around, set "scaleFactor" ahead.
int scale = Math.round(JBUI.sysScale(this));
myScaleFactorAccessor.set(this, scale);
Scene scene = getScene();
// If scene is null then it will be set later and super.setEmbeddedScene(..) will init its scale properly,
// otherwise explicitly set scene scale to match JFXPanel.scaleFactor.
if (scene != null) {
TKScene tks = scene.impl_getPeer();
if (tks instanceof EmbeddedSceneInterface) {
((EmbeddedSceneInterface)tks).setPixelScaleFactor(scale);
}
}
}
}
}
@@ -0,0 +1,113 @@
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ui.javafx;
import com.intellij.ide.IdeEventQueue;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.ui.JBColor;
import com.intellij.util.ui.JBUI;
import com.sun.javafx.application.PlatformImpl;
import javafx.application.Platform;
import javafx.embed.swing.JFXPanel;
import javafx.scene.Scene;
import javafx.scene.web.WebEngine;
import javafx.scene.web.WebView;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.util.ArrayList;
import java.util.List;
public class JavaFxHtmlPanel implements Disposable {
@NotNull
private final JPanel myPanelWrapper;
@NotNull
private final List<Runnable> myInitActions = new ArrayList<>();
@Nullable
private JFXPanel myPanel;
@Nullable protected WebView myWebView;
public JavaFxHtmlPanel() {
myPanelWrapper = new JPanel(new BorderLayout());
myPanelWrapper.setBackground(JBColor.background());
ApplicationManager.getApplication().invokeLater(() -> runFX(() -> PlatformImpl.startup(() -> {
myWebView = new WebView();
myWebView.setContextMenuEnabled(false);
myWebView.setZoom(JBUI.scale(1.f));
final WebEngine engine = myWebView.getEngine();
registerListeners(engine);
final Scene scene = new Scene(myWebView);
ApplicationManager.getApplication().invokeLater(() -> runFX(() -> {
myPanel = new JFXPanelWrapper();
Platform.runLater(() -> myPanel.setScene(scene));
setHtml("");
for (Runnable action : myInitActions) {
Platform.runLater(action);
}
myInitActions.clear();
myPanelWrapper.add(myPanel, BorderLayout.CENTER);
myPanelWrapper.repaint();
}));
})));
}
protected void registerListeners(@NotNull WebEngine engine) {
}
private static void runFX(@NotNull Runnable r) {
IdeEventQueue.unsafeNonblockingExecute(r);
}
protected void runInPlatformWhenAvailable(@NotNull Runnable runnable) {
ApplicationManager.getApplication().assertIsDispatchThread();
if (myPanel == null) {
myInitActions.add(runnable);
}
else {
Platform.runLater(runnable);
}
}
@NotNull
public JComponent getComponent() {
return myPanelWrapper;
}
public void setHtml(@NotNull String html) {
final String htmlToRender = prepareHtml(html);
runInPlatformWhenAvailable(() -> getWebViewGuaranteed().getEngine().loadContent(htmlToRender));
}
@NotNull
protected String prepareHtml(@NotNull String html) {
return html;
}
public void render() {
runInPlatformWhenAvailable(() -> {
getWebViewGuaranteed().getEngine().reload();
ApplicationManager.getApplication().invokeLater(myPanelWrapper::repaint);
});
}
@Override
public void dispose() {
}
@NotNull
protected WebView getWebViewGuaranteed() {
if (myWebView == null) {
throw new IllegalStateException("WebView should be initialized by now. Check the caller thread");
}
return myWebView;
}
}