< prev index next >

modules/web/src/ios/java/javafx/scene/web/WebView.java

Print this page


   1 /*
   2  * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  25 
  26 package javafx.scene.web;
  27 
  28 
  29 import javafx.css.CssMetaData;
  30 import javafx.css.StyleableBooleanProperty;
  31 import javafx.css.StyleableDoubleProperty;
  32 import javafx.css.StyleableObjectProperty;
  33 import javafx.css.StyleableProperty;
  34 import javafx.css.converter.BooleanConverter;
  35 import javafx.css.converter.EnumConverter;
  36 import javafx.css.converter.SizeConverter;
  37 import com.sun.javafx.geom.BaseBounds;
  38 import com.sun.javafx.geom.PickRay;
  39 import com.sun.javafx.geom.transform.Affine3D;
  40 import com.sun.javafx.geom.transform.BaseTransform;
  41 import com.sun.javafx.scene.DirtyBits;
  42 import com.sun.javafx.scene.NodeHelper;
  43 import com.sun.javafx.scene.input.PickResultChooser;
  44 import com.sun.java.scene.web.WebViewHelper;


  45 import com.sun.javafx.tk.TKPulseListener;
  46 import com.sun.javafx.tk.Toolkit;
  47 import java.util.ArrayList;
  48 import java.util.Collections;
  49 import java.util.List;
  50 import javafx.beans.property.*;
  51 import javafx.beans.value.ChangeListener;
  52 import javafx.beans.value.ObservableValue;
  53 import javafx.collections.ObservableList;
  54 import javafx.css.Styleable;
  55 import javafx.geometry.Bounds;
  56 import javafx.scene.Node;
  57 import javafx.scene.Parent;
  58 import javafx.scene.Scene;
  59 import javafx.scene.text.FontSmoothingType;
  60 
  61 /**
  62  * {@code WebView} is a {@link javafx.scene.Node} that manages a
  63  * {@link WebEngine} and displays its content. The associated {@code WebEngine}
  64  * is created automatically at construction time and cannot be changed
  65  * afterwards. {@code WebView} handles mouse and some keyboard events, and
  66  * manages scrolling automatically, so there's no need to put it into a
  67  * {@code ScrollPane}.
  68  *
  69  * <p>{@code WebView} objects must be created and accessed solely from the
  70  * FX thread.
  71  * @since JavaFX 2.0
  72  */
  73 final public class WebView extends Parent {
  74     static {
  75         WebViewHelper.setWebViewAccessor(new WebViewHelper.WebViewAccessor() {
  76             @Override
  77                 public NGNode doCreatePeer(Node node) {
  78                 return ((WebView) node).doCreatePeer();
  79             }
  80 
  81             @Override
  82                 public void doUpdatePeer(Node node) {
  83                 ((WebView) node).doUpdatePeer();
  84             }





















  85             });
  86     }
  87 
  88     private static final boolean DEFAULT_CONTEXT_MENU_ENABLED = true;
  89     private static final FontSmoothingType DEFAULT_FONT_SMOOTHING_TYPE = FontSmoothingType.LCD;
  90     private static final double DEFAULT_ZOOM = 1.0;
  91     private static final double DEFAULT_FONT_SCALE = 1.0;
  92     private static final double DEFAULT_MIN_WIDTH = 0;
  93     private static final double DEFAULT_MIN_HEIGHT = 0;
  94     private static final double DEFAULT_PREF_WIDTH = 800;
  95     private static final double DEFAULT_PREF_HEIGHT = 600;
  96     private static final double DEFAULT_MAX_WIDTH = Double.MAX_VALUE;
  97     private static final double DEFAULT_MAX_HEIGHT = Double.MAX_VALUE;
  98 
  99     private final WebEngine engine;
 100     // pointer to native WebViewImpl
 101     private final long handle;
 102 
 103     /**
 104      * The stage pulse listener registered with the toolkit.


 251      */
 252     public WebView() {
 253         long[] nativeHandle = new long[1];
 254         _initWebView(nativeHandle);
 255         getStyleClass().add("web-view");
 256         handle = nativeHandle[0];
 257         engine = new WebEngine();
 258         engine.setView(this);
 259 
 260         stagePulseListener = () -> {
 261             handleStagePulse();
 262         };
 263         focusedProperty().addListener((ov, t, t1) -> {
 264         });
 265         Toolkit.getToolkit().addStageTkPulseListener(stagePulseListener);
 266 
 267         final ChangeListener<Bounds> chListener = new ChangeListener<Bounds>() {
 268 
 269             @Override
 270             public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
 271                 WebView.this.impl_transformsChanged();
 272             }
 273         };
 274 
 275         parentProperty().addListener(new ChangeListener<Parent>(){
 276 
 277             @Override
 278             public void changed(ObservableValue<? extends Parent> observable, Parent oldValue, Parent newValue) {
 279                 if (oldValue != null && newValue == null) {
 280                     // webview has been removed from scene
 281                     _removeWebView(handle);
 282                 }
 283 
 284                 if (oldValue != null) {
 285                     do {
 286                         oldValue.boundsInParentProperty().removeListener(chListener);
 287                         oldValue = oldValue.getParent();
 288                     } while (oldValue != null);
 289                 }
 290 
 291                 if (newValue != null) {


 315 
 316         impl_treeVisibleProperty().addListener(new ChangeListener<Boolean>() {
 317 
 318             @Override
 319             public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
 320                 _setVisible(handle, newValue);
 321             }
 322         });
 323     }
 324     // Resizing support. Allows arbitrary growing and shrinking.
 325     // Designed after javafx.scene.control.Control
 326 
 327     @Override public boolean isResizable() {
 328         return true;
 329     }
 330 
 331     @Override public void resize(double width, double height) {
 332         this.width.set(width);
 333         this.height.set(height);
 334         NodeHelper.markDirty(this, DirtyBits.NODE_GEOMETRY);
 335         impl_geomChanged();
 336         _setWidth(handle, width);
 337         _setHeight(handle, height);
 338     }
 339 
 340     /**
 341      * Called during layout to determine the minimum width for this node.
 342      *
 343      * @return the minimum width that this node should be resized to during layout
 344      */
 345     @Override public final double minWidth(double height) {
 346         return getMinWidth();
 347     }
 348 
 349     /**
 350      * Called during layout to determine the minimum height for this node.
 351      *
 352      * @return the minimum height that this node should be resized to during layout
 353      */
 354     @Override public final double minHeight(double width) {
 355         return getMinHeight();


 988         // Here the page content is updated before CSS/Layout/Sync pass
 989         // is initiated by the scene pulse. The update may
 990         // change the WebView children and, if so, the children should be
 991         // processed right away during the scene pulse.
 992 
 993         // The WebView node does not render its pending render queues
 994         // while it is invisible. Therefore, we should not schedule new
 995         // render queues while the WebView is invisible to prevent
 996         // the list of render queues from growing infinitely.
 997         // Also, if and when the WebView becomes invisible, the currently
 998         // pending render queues, if any, become obsolete and should be
 999         // discarded.
1000 
1001         boolean reallyVisible = impl_isTreeVisible()
1002                 && getScene() != null
1003                 && getScene().getWindow() != null
1004                 && getScene().getWindow().isShowing();
1005 
1006         if (reallyVisible) {
1007             if (NodeHelper.isDirty(this, DirtyBits.WEBVIEW_VIEW)) {
1008                 Scene.impl_setAllowPGAccess(true);
1009                 //getPGWebView().update(); // creates new render queues
1010                 Scene.impl_setAllowPGAccess(false);
1011             }
1012         } else {
1013             _setVisible(handle, false);
1014         }
1015     }
1016 
1017     /**
1018      * @treatAsPrivate implementation detail
1019      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1020      */
1021     @Deprecated
1022     @Override protected void impl_pickNodeLocal(PickRay pickRay, PickResultChooser result) {
1023         impl_intersects(pickRay, result);
1024     }
1025 
1026     @Override protected ObservableList<Node> getChildren() {
1027         return super.getChildren();
1028     }
1029 
1030     // Node stuff
1031 
1032     /*
1033      * Note: This method MUST only be called via its accessor method.
1034      */
1035     private NGNode doCreatePeer() {
1036         // return new NGWebView();
1037         return null; // iOS doesn't need this method.
1038     }
1039 
1040     /**
1041      * @treatAsPrivate implementation detail
1042      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1043      */
1044     @Deprecated
1045     @Override public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) {
1046         bounds.deriveWithNewBounds(0, 0, 0, (float) getWidth(), (float)getHeight(), 0);
1047         tx.transform(bounds, bounds);
1048         return bounds;
1049     }
1050 
1051     /**
1052      * @treatAsPrivate implementation detail
1053      * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1054      */
1055     @Deprecated
1056     @Override protected boolean impl_computeContains(double localX, double localY) {
1057         // Note: Local bounds contain test is already done by the caller. (Node.contains()).
1058         return true;
1059     }
1060 
1061     /*
1062      * Note: This method MUST only be called via its accessor method.
1063      */
1064     private void doUpdatePeer() {
1065         //PGWebView peer = getPGWebView();
1066 
1067         if (NodeHelper.isDirty(this, DirtyBits.NODE_GEOMETRY)) {
1068             //peer.resize((float)getWidth(), (float)getHeight());
1069         }
1070         if (NodeHelper.isDirty(this, DirtyBits.WEBVIEW_VIEW)) {
1071             //peer.requestRender();
1072         }
1073     }
1074 
1075     private static Affine3D calculateNodeToSceneTransform(Node node) {
1076         final Affine3D transform = new Affine3D();
1077         do {
1078             transform.preConcatenate(node.impl_getLeafTransform());
1079             node = node.getParent();
1080         } while (node != null);
1081 
1082         return transform;
1083     }
1084 
1085     @Deprecated
1086     @Override public void impl_transformsChanged() {
1087         super.impl_transformsChanged();
1088 
1089         Affine3D trans = calculateNodeToSceneTransform(this);
1090         _setTransform(handle,
1091                 trans.getMxx(), trans.getMxy(), trans.getMxz(), trans.getMxt(),
1092                 trans.getMyx(), trans.getMyy(), trans.getMyz(), trans.getMyt(),
1093                 trans.getMzx(), trans.getMzy(), trans.getMzz(), trans.getMzt());
1094     }
1095 
1096     long getNativeHandle() {
1097         return handle;
1098     }
1099 
1100 
1101     // native callbacks
1102     private void notifyLoadStarted() {
1103         engine.notifyLoadStarted();
1104     }
1105     private void notifyLoadFinished(String loc, String content) {
1106         engine.notifyLoadFinished(loc, content);
1107     }
1108     private void notifyLoadFailed() {


   1 /*
   2  * Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any


  25 
  26 package javafx.scene.web;
  27 
  28 
  29 import javafx.css.CssMetaData;
  30 import javafx.css.StyleableBooleanProperty;
  31 import javafx.css.StyleableDoubleProperty;
  32 import javafx.css.StyleableObjectProperty;
  33 import javafx.css.StyleableProperty;
  34 import javafx.css.converter.BooleanConverter;
  35 import javafx.css.converter.EnumConverter;
  36 import javafx.css.converter.SizeConverter;
  37 import com.sun.javafx.geom.BaseBounds;
  38 import com.sun.javafx.geom.PickRay;
  39 import com.sun.javafx.geom.transform.Affine3D;
  40 import com.sun.javafx.geom.transform.BaseTransform;
  41 import com.sun.javafx.scene.DirtyBits;
  42 import com.sun.javafx.scene.NodeHelper;
  43 import com.sun.javafx.scene.input.PickResultChooser;
  44 import com.sun.java.scene.web.WebViewHelper;
  45 import com.sun.javafx.scene.SceneHelper;
  46 import com.sun.javafx.sg.prism.NGNode;
  47 import com.sun.javafx.tk.TKPulseListener;
  48 import com.sun.javafx.tk.Toolkit;
  49 import java.util.ArrayList;
  50 import java.util.Collections;
  51 import java.util.List;
  52 import javafx.beans.property.*;
  53 import javafx.beans.value.ChangeListener;
  54 import javafx.beans.value.ObservableValue;
  55 import javafx.collections.ObservableList;
  56 import javafx.css.Styleable;
  57 import javafx.geometry.Bounds;
  58 import javafx.scene.Node;
  59 import javafx.scene.Parent;

  60 import javafx.scene.text.FontSmoothingType;
  61 
  62 /**
  63  * {@code WebView} is a {@link javafx.scene.Node} that manages a
  64  * {@link WebEngine} and displays its content. The associated {@code WebEngine}
  65  * is created automatically at construction time and cannot be changed
  66  * afterwards. {@code WebView} handles mouse and some keyboard events, and
  67  * manages scrolling automatically, so there's no need to put it into a
  68  * {@code ScrollPane}.
  69  *
  70  * <p>{@code WebView} objects must be created and accessed solely from the
  71  * FX thread.
  72  * @since JavaFX 2.0
  73  */
  74 final public class WebView extends Parent {
  75     static {
  76         WebViewHelper.setWebViewAccessor(new WebViewHelper.WebViewAccessor() {
  77             @Override
  78                 public NGNode doCreatePeer(Node node) {
  79                 return ((WebView) node).doCreatePeer();
  80             }
  81 
  82             @Override
  83                 public void doUpdatePeer(Node node) {
  84                 ((WebView) node).doUpdatePeer();
  85             }
  86 
  87             @Override
  88             public void doTransformsChanged(Node node) {
  89                 ((WebView) node).doTransformsChanged();
  90             }
  91 
  92             @Override
  93             public BaseBounds doComputeGeomBounds(Node node,
  94             BaseBounds bounds, BaseTransform tx) {
  95                 return ((WebView) node).doComputeGeomBounds(bounds, tx);
  96             }
  97 
  98             @Override
  99             public boolean doComputeContains(Node node, double localX, double localY) {
 100                 return ((WebView) node).doComputeContains(localX, localY);
 101             }
 102 
 103             @Override
 104             public void doPickNodeLocal(Node node, PickRay localPickRay, PickResultChooser result) {
 105                 throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
 106             }
 107         });
 108     }
 109 
 110     private static final boolean DEFAULT_CONTEXT_MENU_ENABLED = true;
 111     private static final FontSmoothingType DEFAULT_FONT_SMOOTHING_TYPE = FontSmoothingType.LCD;
 112     private static final double DEFAULT_ZOOM = 1.0;
 113     private static final double DEFAULT_FONT_SCALE = 1.0;
 114     private static final double DEFAULT_MIN_WIDTH = 0;
 115     private static final double DEFAULT_MIN_HEIGHT = 0;
 116     private static final double DEFAULT_PREF_WIDTH = 800;
 117     private static final double DEFAULT_PREF_HEIGHT = 600;
 118     private static final double DEFAULT_MAX_WIDTH = Double.MAX_VALUE;
 119     private static final double DEFAULT_MAX_HEIGHT = Double.MAX_VALUE;
 120 
 121     private final WebEngine engine;
 122     // pointer to native WebViewImpl
 123     private final long handle;
 124 
 125     /**
 126      * The stage pulse listener registered with the toolkit.


 273      */
 274     public WebView() {
 275         long[] nativeHandle = new long[1];
 276         _initWebView(nativeHandle);
 277         getStyleClass().add("web-view");
 278         handle = nativeHandle[0];
 279         engine = new WebEngine();
 280         engine.setView(this);
 281 
 282         stagePulseListener = () -> {
 283             handleStagePulse();
 284         };
 285         focusedProperty().addListener((ov, t, t1) -> {
 286         });
 287         Toolkit.getToolkit().addStageTkPulseListener(stagePulseListener);
 288 
 289         final ChangeListener<Bounds> chListener = new ChangeListener<Bounds>() {
 290 
 291             @Override
 292             public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
 293                 NodeHelper.transformsChanged(WebView.this);
 294             }
 295         };
 296 
 297         parentProperty().addListener(new ChangeListener<Parent>(){
 298 
 299             @Override
 300             public void changed(ObservableValue<? extends Parent> observable, Parent oldValue, Parent newValue) {
 301                 if (oldValue != null && newValue == null) {
 302                     // webview has been removed from scene
 303                     _removeWebView(handle);
 304                 }
 305 
 306                 if (oldValue != null) {
 307                     do {
 308                         oldValue.boundsInParentProperty().removeListener(chListener);
 309                         oldValue = oldValue.getParent();
 310                     } while (oldValue != null);
 311                 }
 312 
 313                 if (newValue != null) {


 337 
 338         impl_treeVisibleProperty().addListener(new ChangeListener<Boolean>() {
 339 
 340             @Override
 341             public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
 342                 _setVisible(handle, newValue);
 343             }
 344         });
 345     }
 346     // Resizing support. Allows arbitrary growing and shrinking.
 347     // Designed after javafx.scene.control.Control
 348 
 349     @Override public boolean isResizable() {
 350         return true;
 351     }
 352 
 353     @Override public void resize(double width, double height) {
 354         this.width.set(width);
 355         this.height.set(height);
 356         NodeHelper.markDirty(this, DirtyBits.NODE_GEOMETRY);
 357         NodeHelper.geomChanged(this);
 358         _setWidth(handle, width);
 359         _setHeight(handle, height);
 360     }
 361 
 362     /**
 363      * Called during layout to determine the minimum width for this node.
 364      *
 365      * @return the minimum width that this node should be resized to during layout
 366      */
 367     @Override public final double minWidth(double height) {
 368         return getMinWidth();
 369     }
 370 
 371     /**
 372      * Called during layout to determine the minimum height for this node.
 373      *
 374      * @return the minimum height that this node should be resized to during layout
 375      */
 376     @Override public final double minHeight(double width) {
 377         return getMinHeight();


1010         // Here the page content is updated before CSS/Layout/Sync pass
1011         // is initiated by the scene pulse. The update may
1012         // change the WebView children and, if so, the children should be
1013         // processed right away during the scene pulse.
1014 
1015         // The WebView node does not render its pending render queues
1016         // while it is invisible. Therefore, we should not schedule new
1017         // render queues while the WebView is invisible to prevent
1018         // the list of render queues from growing infinitely.
1019         // Also, if and when the WebView becomes invisible, the currently
1020         // pending render queues, if any, become obsolete and should be
1021         // discarded.
1022 
1023         boolean reallyVisible = impl_isTreeVisible()
1024                 && getScene() != null
1025                 && getScene().getWindow() != null
1026                 && getScene().getWindow().isShowing();
1027 
1028         if (reallyVisible) {
1029             if (NodeHelper.isDirty(this, DirtyBits.WEBVIEW_VIEW)) {
1030                 SceneHelper.setAllowPGAccess(true);
1031                 //getPGWebView().update(); // creates new render queues
1032                 SceneHelper.setAllowPGAccess(false);
1033             }
1034         } else {
1035             _setVisible(handle, false);
1036         }
1037     }
1038 









1039     @Override protected ObservableList<Node> getChildren() {
1040         return super.getChildren();
1041     }
1042 
1043     // Node stuff
1044 
1045     /*
1046      * Note: This method MUST only be called via its accessor method.
1047      */
1048     private NGNode doCreatePeer() {
1049         // return new NGWebView();
1050         return null; // iOS doesn't need this method.
1051     }
1052 
1053     /*
1054      * Note: This method MUST only be called via its accessor method.

1055      */
1056     private BaseBounds doComputeGeomBounds(BaseBounds bounds, BaseTransform tx) {

1057         bounds.deriveWithNewBounds(0, 0, 0, (float) getWidth(), (float)getHeight(), 0);
1058         tx.transform(bounds, bounds);
1059         return bounds;
1060     }
1061 
1062     /*
1063      * Note: This method MUST only be called via its accessor method.

1064      */
1065     private boolean doComputeContains(double localX, double localY) {

1066         // Note: Local bounds contain test is already done by the caller. (Node.contains()).
1067         return true;
1068     }
1069 
1070     /*
1071      * Note: This method MUST only be called via its accessor method.
1072      */
1073     private void doUpdatePeer() {
1074         //PGWebView peer = getPGWebView();
1075 
1076         if (NodeHelper.isDirty(this, DirtyBits.NODE_GEOMETRY)) {
1077             //peer.resize((float)getWidth(), (float)getHeight());
1078         }
1079         if (NodeHelper.isDirty(this, DirtyBits.WEBVIEW_VIEW)) {
1080             //peer.requestRender();
1081         }
1082     }
1083 
1084     private static Affine3D calculateNodeToSceneTransform(Node node) {
1085         final Affine3D transform = new Affine3D();
1086         do {
1087             transform.preConcatenate(NodeHelper.getLeafTransform(node));
1088             node = node.getParent();
1089         } while (node != null);
1090 
1091         return transform;
1092     }
1093 
1094     /*
1095      * Note: This method MUST only be called via its accessor method.
1096      */
1097     private void doTransformsChanged() {
1098         Affine3D trans = calculateNodeToSceneTransform(this);
1099         _setTransform(handle,
1100                 trans.getMxx(), trans.getMxy(), trans.getMxz(), trans.getMxt(),
1101                 trans.getMyx(), trans.getMyy(), trans.getMyz(), trans.getMyt(),
1102                 trans.getMzx(), trans.getMzy(), trans.getMzz(), trans.getMzt());
1103     }
1104 
1105     long getNativeHandle() {
1106         return handle;
1107     }
1108 
1109 
1110     // native callbacks
1111     private void notifyLoadStarted() {
1112         engine.notifyLoadStarted();
1113     }
1114     private void notifyLoadFinished(String loc, String content) {
1115         engine.notifyLoadFinished(loc, content);
1116     }
1117     private void notifyLoadFailed() {


< prev index next >