You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@isis.apache.org by ah...@apache.org on 2020/06/29 18:57:39 UTC
[isis] branch master updated: ISIS-2340: fx: WebView with autofit,
to render Markup types
This is an automated email from the ASF dual-hosted git repository.
ahuber pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/isis.git
The following commit(s) were added to refs/heads/master by this push:
new 0bf0750 ISIS-2340: fx: WebView with autofit, to render Markup types
0bf0750 is described below
commit 0bf0750f39afc3e7f83f5086f7b03a262762f662
Author: Andi Huber <ah...@apache.org>
AuthorDate: Mon Jun 29 20:57:23 2020 +0200
ISIS-2340: fx: WebView with autofit, to render Markup types
---
.../javafx/ui/components/form/SimpleFormField.java | 41 ++++++++
.../ui/components/markup/MarkupFieldFactory.java | 116 ++++++++++++++++-----
.../ui/components/other/FallbackFieldFactory.java | 21 +---
3 files changed, 134 insertions(+), 44 deletions(-)
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/form/SimpleFormField.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/form/SimpleFormField.java
new file mode 100644
index 0000000..e06faef
--- /dev/null
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/form/SimpleFormField.java
@@ -0,0 +1,41 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.isis.incubator.viewer.javafx.ui.components.form;
+
+import org.apache.isis.applib.annotation.LabelPosition;
+
+import lombok.Getter;
+import lombok.RequiredArgsConstructor;
+
+import javafx.scene.Node;
+
+@RequiredArgsConstructor
+public class SimpleFormField implements FormField {
+
+ @Getter(onMethod_ = {@Override})
+ protected final LabelPosition labelPosition;
+
+ @Getter(onMethod_ = {@Override})
+ protected final Node uiLabel;
+
+ @Getter(onMethod_ = {@Override})
+ protected final Node uiField;
+
+
+}
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/markup/MarkupFieldFactory.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/markup/MarkupFieldFactory.java
index 7067841..32e2932 100644
--- a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/markup/MarkupFieldFactory.java
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/markup/MarkupFieldFactory.java
@@ -23,15 +23,26 @@ import org.springframework.core.annotation.Order;
import org.apache.isis.applib.annotation.LabelPosition;
import org.apache.isis.applib.annotation.OrderPrecedence;
import org.apache.isis.applib.value.Markup;
+import org.apache.isis.core.metamodel.facets.objectvalue.labelat.LabelAtFacet;
import org.apache.isis.incubator.viewer.javafx.ui.components.UiComponentHandlerFx;
import org.apache.isis.incubator.viewer.javafx.ui.components.form.FormField;
+import org.apache.isis.incubator.viewer.javafx.ui.components.form.SimpleFormField;
import org.apache.isis.viewer.common.model.binding.UiComponentFactory.Request;
import lombok.val;
+import lombok.extern.log4j.Log4j2;
+import javafx.application.Platform;
+import javafx.collections.ListChangeListener;
+import javafx.concurrent.Worker.State;
+import javafx.geometry.HPos;
+import javafx.geometry.VPos;
import javafx.scene.Node;
import javafx.scene.control.Label;
-import javafx.scene.control.TextArea;
+import javafx.scene.layout.Region;
+import javafx.scene.web.WebEngine;
+import javafx.scene.web.WebView;
+import netscape.javascript.JSException;
@org.springframework.stereotype.Component
@Order(OrderPrecedence.MIDPOINT)
@@ -49,34 +60,89 @@ public class MarkupFieldFactory implements UiComponentHandlerFx {
.map(Markup::asString)
.orElse("");
-//XXX Unfortunately we have no simple means of auto-fitting a WebView
-// val uiComponent = new WebView();
-// uiComponent.getEngine().loadContent(markupHtml, "text/html");
-
- val uiComponent = new TextArea(markupHtml);
- uiComponent.setPrefHeight(40);
+ val uiComponent = new WebViewFitContent(markupHtml);
val uiLabel = new Label(request.getFeatureLabel());
- return new FormField() {
-
- @Override
- public Node getUiLabel() {
- return uiLabel;
- }
-
- @Override
- public Node getUiField() {
- return uiComponent;
- }
-
- @Override
- public LabelPosition getLabelPosition() {
- // TODO Auto-generated method stub
- return null;
- }
- };
+ val labelPosition = request.getFeatureFacet(LabelAtFacet.class)
+ .map(LabelAtFacet::label)
+ .orElse(LabelPosition.NOT_SPECIFIED);
+
+ return new SimpleFormField(labelPosition, uiLabel, uiComponent);
}
+ // -- HELPER
+
+ /**
+ * Unfortunately we have no simple means of auto-fitting a WebView, so we need a wrapper,
+ * that executes some JavaScript on the rendered content, do determine the preferred height.
+ * <p>
+ * @see <a href="https://stackoverflow.com/questions/25838965/size-javafx-webview-to-the-minimum-size-needed-by-the-document-body">stackoverflow</a>
+ *
+ * @since Jun 29, 2020
+ */
+ @Log4j2
+ private static final class WebViewFitContent extends Region {
+
+ final WebView webview = new WebView();
+ final WebEngine webEngine = webview.getEngine();
+
+ public WebViewFitContent(String content) {
+ webview.setPrefHeight(5);
+
+ widthProperty().addListener((e, o, newWidth) -> {
+ webview.setPrefWidth(newWidth.doubleValue());
+ Platform.runLater(this::adjustHeight);
+ });
+
+ webview.getEngine().getLoadWorker().stateProperty().addListener((e, o, newState) -> {
+ if (newState == State.SUCCEEDED) {
+ Platform.runLater(this::adjustHeight);
+ }
+ });
+
+ webview.getChildrenUnmodifiable().addListener((ListChangeListener.Change<? extends Node> change) -> {
+ val scrolls = webview.lookupAll(".scroll-bar");
+ for (val scroll : scrolls) {
+ scroll.setVisible(false);
+ }
+ });
+
+ setContent(content);
+ getChildren().add(webview);
+ }
+
+ public void setContent(final String content) {
+ Platform.runLater(()->webEngine.loadContent(getHtml(content), "text/html"));
+ Platform.runLater(this::adjustHeight);
+ }
+
+ @Override
+ protected void layoutChildren() {
+ layoutInArea(webview, 0, 0, getWidth(), getHeight(), 0, HPos.CENTER, VPos.CENTER);
+ }
+
+ private void adjustHeight() {
+ try {
+ Object result = webEngine.executeScript(
+ "var myDiv = document.getElementById('mydiv');" +
+ "if (myDiv != null) myDiv.offsetHeight");
+ if (result instanceof Integer) {
+ val height = ((Integer) result).intValue();
+ webview.setPrefHeight(height + 20);
+ }
+ } catch (JSException e) {
+ log.error("failed to execute JavaScript to determine WebView's height", e);
+ }
+ }
+
+ private String getHtml(String content) {
+ return "<html><body>" +
+ "<div id=\"mydiv\">" + content + "</div>" +
+ "</body></html>";
+ }
+
+ }
+
}
diff --git a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/other/FallbackFieldFactory.java b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/other/FallbackFieldFactory.java
index 9821d60..d43ce7d 100644
--- a/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/other/FallbackFieldFactory.java
+++ b/incubator/viewers/javafx/ui/src/main/java/org/apache/isis/incubator/viewer/javafx/ui/components/other/FallbackFieldFactory.java
@@ -34,12 +34,12 @@ import org.apache.isis.incubator.viewer.javafx.ui.components.UiComponentFactoryF
import org.apache.isis.incubator.viewer.javafx.ui.components.UiComponentHandlerFx;
import org.apache.isis.incubator.viewer.javafx.ui.components.debug.DebugField;
import org.apache.isis.incubator.viewer.javafx.ui.components.form.FormField;
+import org.apache.isis.incubator.viewer.javafx.ui.components.form.SimpleFormField;
import org.apache.isis.viewer.common.model.binding.UiComponentFactory.Request;
import org.apache.isis.viewer.common.model.debug.DebugUiModel;
import lombok.val;
-import javafx.scene.Node;
import javafx.scene.control.Label;
@org.springframework.stereotype.Component
@@ -82,24 +82,7 @@ public class FallbackFieldFactory implements UiComponentHandlerFx {
val uiLabel = new Label(request.getFeatureLabel());
- return new FormField() {
-
- @Override
- public Node getUiLabel() {
- return uiLabel;
- }
-
- @Override
- public Node getUiField() {
- return debugField;
- }
-
- @Override
- public LabelPosition getLabelPosition() {
- return LabelPosition.TOP;
- }
- };
-
+ return new SimpleFormField(LabelPosition.TOP, uiLabel, debugField);
}
private String summarize(Facet facet) {