+++ /dev/null
-// Copyright 2000-2019 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.ui.JreHiDpiUtil;
-import com.intellij.ui.scale.JBUIScale;
-import com.intellij.util.FieldAccessor;
-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", Integer.TYPE);
-
- 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() {
- // todo: remove it when IDEA finally switches to JFX10
- if (myScaleFactorAccessor.isAvailable()) {
- if (JreHiDpiUtil.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(JBUIScale.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);
- }
- }
- }
- }
- // change scale factor before component will be resized in super
- super.addNotify();
- }
-}
+++ /dev/null
-// Copyright 2000-2019 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.ide.ui.LafManager;
-import com.intellij.ide.ui.LafManagerListener;
-import com.intellij.ide.ui.laf.darcula.DarculaLookAndFeelInfo;
-import com.intellij.ide.util.PropertiesComponent;
-import com.intellij.openapi.Disposable;
-import com.intellij.openapi.application.ApplicationManager;
-import com.intellij.ui.JBColor;
-import com.intellij.ui.scale.JBUIScale;
-import com.intellij.util.ui.StartupUiUtil;
-import com.sun.javafx.application.PlatformImpl;
-import com.sun.javafx.webkit.Accessor;
-import com.sun.webkit.WebPage;
-import javafx.application.Platform;
-import javafx.concurrent.Worker;
-import javafx.embed.swing.JFXPanel;
-import javafx.scene.Scene;
-import javafx.scene.text.FontSmoothingType;
-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.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-
-public class JavaFxHtmlPanel implements Disposable {
- // flag is reset after check
- public static final String JAVAFX_INITIALIZATION_INCOMPLETE_PROPERTY = "js.debugger.javafx.inititalization";
- @NotNull
- private final JPanel myPanelWrapper;
- @NotNull
- private final List<Runnable> myInitActions = new ArrayList<>();
- @Nullable
- protected JFXPanel myPanel;
- @Nullable protected WebView myWebView;
- private Color background;
-
- public JavaFxHtmlPanel() {
- PropertiesComponent.getInstance().setValue(JAVAFX_INITIALIZATION_INCOMPLETE_PROPERTY, true, false);
- ApplicationManager.getApplication().saveSettings();
- background = JBColor.background();
- myPanelWrapper = new JPanel(new BorderLayout());
- myPanelWrapper.setBackground(background);
-
- ApplicationManager.getApplication().invokeLater(() -> runFX(() -> PlatformImpl.startup(() -> {
- PropertiesComponent.getInstance().setValue(JAVAFX_INITIALIZATION_INCOMPLETE_PROPERTY, false, false);
- myWebView = new WebView();
- myWebView.setContextMenuEnabled(false);
- myWebView.setZoom(JBUIScale.scale(1.f));
- myWebView.fontSmoothingTypeProperty().setValue(FontSmoothingType.GRAY);
-
- final WebEngine engine = myWebView.getEngine();
- registerListeners(engine);
- engine.getLoadWorker().stateProperty().addListener((observable, oldValue, newValue) -> {
- if (newValue == Worker.State.RUNNING) {
- WebPage page = Accessor.getPageFor(engine);
- page.setBackgroundColor(background.getRGB());
- }
- }
- );
-
- javafx.scene.paint.Color fxColor = toFxColor(background);
- final Scene scene = new Scene(myWebView, fxColor);
-
- 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();
- }));
- })));
-
- ApplicationManager.getApplication().getMessageBus().connect(this).subscribe(LafManagerListener.TOPIC, new JavaFXLafManagerListener());
- runInPlatformWhenAvailable(() -> updateLaf(StartupUiUtil.isUnderDarcula()));
- }
-
- @NotNull
- public static javafx.scene.paint.Color toFxColor(Color background) {
- double r = background.getRed() / 255.0;
- double g = background.getGreen() / 255.0;
- double b = background.getBlue() / 255.0;
- double a = background.getAlpha() / 255.0;
- return javafx.scene.paint.Color.color(r, g, b, a);
- }
-
- public void setBackground(Color background) {
- this.background = background;
- myPanelWrapper.setBackground(background);
- ApplicationManager.getApplication().invokeLater(() -> runFX(() -> {
- if (myPanel != null) {
- myPanel.getScene().setFill(toFxColor(background));
- }
- }));
- }
-
- 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);
- });
- }
-
- /**
- * @return user style, used to display HTML
- * @see WebEngine#setUserStyleSheetLocation(String)
- * @see #getJavaFxStyle(boolean)
- */
- @Nullable
- protected URL getStyle(boolean isDarcula) {
- return null;
- }
-
- /**
- * @return java fx style, used for menus etc.
- * See <a href="https://docs.oracle.com/javafx/2/api/javafx/scene/doc-files/cssref.html">manual</a>
- * @see Scene#getStylesheets()
- * @see #getStyle(boolean)
- */
- @Nullable
- protected URL getJavaFxStyle(boolean isDarcula) {
- return null;
- }
-
-
- private class JavaFXLafManagerListener implements LafManagerListener {
- @Override
- public void lookAndFeelChanged(@NotNull LafManager manager) {
- updateLaf(manager.getCurrentLookAndFeel() instanceof DarculaLookAndFeelInfo);
- }
- }
-
- private void updateLaf(boolean isDarcula) {
- @Nullable
- URL userAgentStyle = getStyle(isDarcula);
- @Nullable
- URL javaFxStyle = getJavaFxStyle(isDarcula);
- if (userAgentStyle == null && javaFxStyle == null) {
- return;
- }
- ApplicationManager.getApplication().invokeLater(
- () -> runInPlatformWhenAvailable(
- () -> {
- final WebView webView = getWebViewGuaranteed();
- if (userAgentStyle != null) {
- webView.getEngine().setUserStyleSheetLocation(userAgentStyle.toExternalForm());
- }
- if (javaFxStyle != null) {
- webView.getScene().getStylesheets().add(javaFxStyle.toExternalForm());
- }
- }
- ));
- }
-
- @Override
- public void dispose() {
- runInPlatformWhenAvailable(() -> getWebViewGuaranteed().getEngine().load(null));
- }
-
-
- @NotNull
- protected WebView getWebViewGuaranteed() {
- if (myWebView == null) {
- throw new IllegalStateException("WebView should be initialized by now. Check the caller thread");
- }
- return myWebView;
- }
-}