Spec-Zone .ru
спецификации, руководства, описания, API
001/*
002 * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation.  Oracle designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Oracle in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
022 * or visit www.oracle.com if you need additional information or have any
023 * questions.
024 */
025
026package javafx.scene.web;
027
028
029import javafx.css.CssMetaData;
030import javafx.css.StyleableBooleanProperty;
031import javafx.css.StyleableDoubleProperty;
032import javafx.css.StyleableObjectProperty;
033import javafx.css.StyleableProperty;
034import com.sun.javafx.css.converters.BooleanConverter;
035import com.sun.javafx.css.converters.EnumConverter;
036import com.sun.javafx.css.converters.SizeConverter;
037import com.sun.javafx.geom.BaseBounds;
038import com.sun.javafx.geom.PickRay;
039import com.sun.javafx.geom.transform.Affine3D;
040import com.sun.javafx.geom.transform.BaseTransform;
041import com.sun.javafx.scene.DirtyBits;
042import com.sun.javafx.scene.input.PickResultChooser;
043import com.sun.javafx.tk.TKPulseListener;
044import com.sun.javafx.tk.Toolkit;
045import java.util.ArrayList;
046import java.util.Collections;
047import java.util.List;
048import javafx.beans.property.*;
049import javafx.beans.value.ChangeListener;
050import javafx.beans.value.ObservableValue;
051import javafx.collections.ObservableList;
052import javafx.css.Styleable;
053import javafx.geometry.Bounds;
054import javafx.geometry.Point3D;
055import javafx.scene.Node;
056import javafx.scene.Parent;
057import javafx.scene.Scene;
058import javafx.scene.text.FontSmoothingType;
059
060/**
061 * {@code WebView} is a {@link javafx.scene.Node} that manages a
062 * {@link WebEngine} and displays its content. The associated {@code WebEngine}
063 * is created automatically at construction time and cannot be changed
064 * afterwards. {@code WebView} handles mouse and some keyboard events, and
065 * manages scrolling automatically, so there's no need to put it into a
066 * {@code ScrollPane}.
067 * 
068 * <p>{@code WebView} objects must be created and accessed solely from the
069 * FX thread.
070 */
071final public class WebView extends Parent {
072
073    private static final boolean DEFAULT_CONTEXT_MENU_ENABLED = true;
074    private static final FontSmoothingType DEFAULT_FONT_SMOOTHING_TYPE = FontSmoothingType.LCD;
075    private static final double DEFAULT_ZOOM = 1.0;
076    private static final double DEFAULT_FONT_SCALE = 1.0;
077    private static final double DEFAULT_MIN_WIDTH = 0;
078    private static final double DEFAULT_MIN_HEIGHT = 0;
079    private static final double DEFAULT_PREF_WIDTH = 800;
080    private static final double DEFAULT_PREF_HEIGHT = 600;
081    private static final double DEFAULT_MAX_WIDTH = Double.MAX_VALUE;
082    private static final double DEFAULT_MAX_HEIGHT = Double.MAX_VALUE;
083    
084    private final WebEngine engine;
085    // pointer to native WebViewImpl
086    private final long handle;
087
088    /**
089     * The stage pulse listener registered with the toolkit.
090     * This field guarantees that the listener will exist throughout
091     * the whole lifetime of the WebView node. This field is necessary
092     * because the toolkit references its stage pulse listeners weakly.
093     */
094    private final TKPulseListener stagePulseListener;
095
096    /**
097     * Returns the {@code WebEngine} object.
098     */
099    public final WebEngine getEngine() {
100        return engine;
101    }
102
103    private final ReadOnlyDoubleWrapper width = new ReadOnlyDoubleWrapper(this, "width");
104
105    /**
106     * Returns width of this {@code WebView}.
107     */
108    public final double getWidth() {
109        return width.get();
110    }
111
112    /**
113     * Width of this {@code WebView}.
114     */
115    public ReadOnlyDoubleProperty widthProperty() {
116        return width.getReadOnlyProperty();
117    }
118
119    private final ReadOnlyDoubleWrapper height = new ReadOnlyDoubleWrapper(this, "height");
120
121    /**
122     * Returns height of this {@code WebView}.
123     */
124    public final double getHeight() {
125        return height.get();
126    }
127
128    /**
129     * Height of this {@code WebView}.
130     */
131    public ReadOnlyDoubleProperty heightProperty() {
132        return height.getReadOnlyProperty();
133    }
134
135    /**
136     * Zoom factor applied to the whole page contents.
137     *
138     * @defaultValue 1.0
139     */
140    private DoubleProperty zoom;
141
142    /**
143     * Sets current zoom factor applied to the whole page contents.
144     * @param value zoom factor to be set
145     * @see #zoomProperty()
146     * @see #getZoom()
147     */
148    public final void setZoom(double value) {
149        WebEngine.checkThread();
150        zoomProperty().set(value);
151    }
152
153    /**
154     * Returns current zoom factor applied to the whole page contents.
155     * @return current zoom factor
156     * @see #zoomProperty()
157     * @see #setZoom(double value)
158     */
159    public final double getZoom() {
160        return (this.zoom != null)
161                ? this.zoom.get()
162                : DEFAULT_ZOOM;
163    }
164
165    /**
166     * Returns zoom property object.
167     * @return zoom property object
168     * @see #getZoom()
169     * @see #setZoom(double value)
170     */
171    public final DoubleProperty zoomProperty() {
172        if (zoom == null) {
173            zoom = new StyleableDoubleProperty(DEFAULT_ZOOM) {
174                @Override public void invalidated() {
175                    Toolkit.getToolkit().checkFxUserThread();
176                }
177
178                @Override public CssMetaData<WebView, Number> getCssMetaData() {
179                    return StyleableProperties.ZOOM;
180                }
181                @Override public Object getBean() {
182                    return WebView.this;
183                }
184                @Override public String getName() {
185                    return "zoom";
186                }
187            };
188        }
189        return zoom;
190    }
191
192    /**
193     * Specifies scale factor applied to font. This setting affects
194     * text content but not images and fixed size elements.
195     *
196     * @defaultValue 1.0
197     */
198    private DoubleProperty fontScale;
199
200    /**
201     * Sets scale factor applied to font.
202     */
203    public final void setFontScale(double value) {
204        WebEngine.checkThread();
205        fontScaleProperty().set(value);
206    }
207
208    /**
209     * Returns scale factor applied to font.
210     */
211    public final double getFontScale() {
212        return (this.fontScale != null)
213                ? this.fontScale.get()
214                : DEFAULT_FONT_SCALE;
215    }
216
217    /**
218     * Scale factor applied to font. This property can be used to make text
219     * larger or smaller but does not affect images and fixed size elements.
220     */
221    public DoubleProperty fontScaleProperty() {
222        if (fontScale == null) {
223            fontScale = new StyleableDoubleProperty(DEFAULT_FONT_SCALE) {
224                @Override public void invalidated() {
225                    Toolkit.getToolkit().checkFxUserThread();
226                }
227                @Override public CssMetaData<WebView, Number> getCssMetaData() {
228                    return StyleableProperties.FONT_SCALE;
229                }
230                @Override public Object getBean() {
231                    return WebView.this;
232                }
233                @Override public String getName() {
234                    return "fontScale";
235                }
236            };
237        }
238        return fontScale;
239    }
240
241    /**
242     * Creates a {@code WebView} object.
243     */
244    public WebView() {
245        long[] nativeHandle = new long[1];
246        _initWebView(nativeHandle);
247        getStyleClass().add("web-view");
248        handle = nativeHandle[0];
249        engine = new WebEngine();
250        engine.setView(this);
251
252        stagePulseListener = new TKPulseListener() {
253            @Override public void pulse() {
254                handleStagePulse();
255            }
256        };
257        focusedProperty().addListener(new ChangeListener<Boolean>() {
258
259            @Override
260            public void changed(ObservableValue<? extends Boolean> ov, Boolean t, Boolean t1) {
261
262            }
263        });
264        Toolkit.getToolkit().addStageTkPulseListener(stagePulseListener);
265        
266        final ChangeListener<Bounds> chListener = new ChangeListener<Bounds>() {
267
268            @Override
269            public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
270                WebView.this.impl_transformsChanged();
271            }
272        };
273        
274        parentProperty().addListener(new ChangeListener<Parent>(){
275            
276            @Override
277            public void changed(ObservableValue<? extends Parent> observable, Parent oldValue, Parent newValue) {                
278                if (oldValue != null && newValue == null) {
279                    // webview has been removed from scene
280                    _removeWebView(handle);
281                }
282                
283                if (oldValue != null) {
284                    do {
285                        oldValue.boundsInParentProperty().removeListener(chListener);
286                        oldValue = oldValue.getParent();
287                    } while (oldValue != null);
288                }
289                
290                if (newValue != null) {
291                    do {
292                        final Node n = newValue;
293                        newValue.boundsInParentProperty().addListener(chListener);
294                        newValue = newValue.getParent();
295                    } while (newValue != null);
296                }
297            }
298            
299        });
300        
301        layoutBoundsProperty().addListener(new ChangeListener<Bounds>() {
302
303            @Override
304            public void changed(ObservableValue<? extends Bounds> observable, Bounds oldValue, Bounds newValue) {
305                Affine3D trans = calculateNodeToSceneTransform(WebView.this);
306                _setTransform(handle,
307                trans.getMxx(), trans.getMxy(), trans.getMxz(), trans.getMxt(),
308                trans.getMyx(), trans.getMyy(), trans.getMyz(), trans.getMyt(),
309                trans.getMzx(), trans.getMzy(), trans.getMzz(), trans.getMzt());
310                
311            }
312            
313        });
314        
315        impl_treeVisibleProperty().addListener(new ChangeListener<Boolean>() {
316
317            @Override
318            public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
319                _setVisible(handle, newValue);
320            }
321        });
322    }
323    // Resizing support. Allows arbitrary growing and shrinking.
324    // Designed after javafx.scene.control.Control
325
326    @Override public boolean isResizable() {
327        return true;
328    }
329
330    @Override public void resize(double width, double height) {
331        this.width.set(width);
332        this.height.set(height);
333        impl_markDirty(DirtyBits.NODE_GEOMETRY);
334        impl_geomChanged();
335        _setWidth(handle, width);
336        _setHeight(handle, height);
337    }
338
339    /**
340     * Called during layout to determine the minimum width for this node.
341     *
342     * @return the minimum width that this node should be resized to during layout
343     */
344    @Override public final double minWidth(double height) {
345        return getMinWidth();
346    }
347
348    /**
349     * Called during layout to determine the minimum height for this node.
350     *
351     * @return the minimum height that this node should be resized to during layout
352     */
353    @Override public final double minHeight(double width) {
354        return getMinHeight();
355    }
356
357
358    /**
359     * Called during layout to determine the preferred width for this node.
360     *
361     * @return the preferred width that this node should be resized to during layout
362     */
363    @Override public final double prefWidth(double height) {
364        return getPrefWidth();
365    }
366
367    /**
368     * Called during layout to determine the preferred height for this node.
369     *
370     * @return the preferred height that this node should be resized to during layout
371     */
372    @Override public final double prefHeight(double width) {
373        return getPrefHeight();
374    }
375    /**
376     * Called during layout to determine the maximum width for this node.
377     *
378     * @return the maximum width that this node should be resized to during layout
379     */
380    @Override public final double maxWidth(double height) {
381        return getMaxWidth();
382    }
383
384    /**
385     * Called during layout to determine the maximum height for this node.
386     *
387     * @return the maximum height that this node should be resized to during layout
388     */
389    @Override public final double maxHeight(double width) {
390        return getMaxHeight();
391    }
392
393    /**
394     * Minimum width property.
395     */
396    public DoubleProperty minWidthProperty() {
397        if (minWidth == null) {
398            minWidth = new StyleableDoubleProperty(DEFAULT_MIN_WIDTH) {
399                @Override
400                public void invalidated() {
401                    if (getParent() != null) {
402                        getParent().requestLayout();
403                    }
404                }
405                @Override
406                public CssMetaData<WebView, Number> getCssMetaData() {
407                    return StyleableProperties.MIN_WIDTH;
408                }
409                @Override
410                public Object getBean() {
411                    return WebView.this;
412                }
413                @Override
414                public String getName() {
415                    return "minWidth";
416                }
417            };
418        }
419        return minWidth;
420    }
421    private DoubleProperty minWidth;
422    
423    /**
424     * Sets minimum width.
425     */
426    public final void setMinWidth(double value) {
427        minWidthProperty().set(value);
428        _setWidth(handle, value);
429    }
430    
431    /**
432     * Returns minimum width.
433     */
434    public final double getMinWidth() {
435        return (this.minWidth != null)
436                ? this.minWidth.get()
437                : DEFAULT_MIN_WIDTH;
438    }
439
440    /**
441     * Minimum height property.
442     */
443    public DoubleProperty minHeightProperty() {
444        if (minHeight == null) {
445            minHeight = new StyleableDoubleProperty(DEFAULT_MIN_HEIGHT) {
446                @Override
447                public void invalidated() {
448                    if (getParent() != null) {
449                        getParent().requestLayout();
450                    }
451                }
452                @Override
453                public CssMetaData<WebView, Number> getCssMetaData() {
454                    return StyleableProperties.MIN_HEIGHT;
455                }
456                @Override
457                public Object getBean() {
458                    return WebView.this;
459                }
460                @Override
461                public String getName() {
462                    return "minHeight";
463                }
464            };
465        }
466        return minHeight;
467    }
468    private DoubleProperty minHeight;
469    
470    /**
471     * Sets minimum height.
472     */
473    public final void setMinHeight(double value) {
474        minHeightProperty().set(value);
475        _setHeight(handle, value);
476    }
477    
478    /**
479     * Sets minimum height.
480     */
481    public final double getMinHeight() {
482        return (this.minHeight != null)
483                ? this.minHeight.get()
484                : DEFAULT_MIN_HEIGHT;
485    }
486
487    /**
488     * Convenience method for setting minimum width and height.
489     */
490    public void setMinSize(double minWidth, double minHeight) {
491        setMinWidth(minWidth);
492        setMinHeight(minHeight);
493        _setWidth(handle, minWidth);
494        _setHeight(handle, minHeight);
495    }
496
497    /**
498     * Preferred width property.
499     */
500    public DoubleProperty prefWidthProperty() {
501        if (prefWidth == null) {
502            prefWidth = new StyleableDoubleProperty(DEFAULT_PREF_WIDTH) {
503                @Override
504                public void invalidated() {
505                    if (getParent() != null) {
506                        getParent().requestLayout();
507                    }
508                }
509                @Override
510                public CssMetaData<WebView, Number> getCssMetaData() {
511                    return StyleableProperties.PREF_WIDTH;
512                }
513                @Override
514                public Object getBean() {
515                    return WebView.this;
516                }
517                @Override
518                public String getName() {
519                    return "prefWidth";
520                }
521            };
522        }
523        return prefWidth;
524    }
525    private DoubleProperty prefWidth;
526    
527    /**
528     * Sets preferred width.
529     */
530    public final void setPrefWidth(double value) {
531        prefWidthProperty().set(value);
532        _setWidth(handle, value);
533    }
534
535    /**
536     * Returns preferred width.
537     */
538    public final double getPrefWidth() {
539        return (this.prefWidth != null)
540                ? this.prefWidth.get()
541                : DEFAULT_PREF_WIDTH;
542    }
543
544    /**
545     * Preferred height property.
546     */
547    public DoubleProperty prefHeightProperty() {
548        if (prefHeight == null) {
549            prefHeight = new StyleableDoubleProperty(DEFAULT_PREF_HEIGHT) {
550                @Override
551                public void invalidated() {
552                    if (getParent() != null) {
553                        getParent().requestLayout();
554                    }
555                }
556                @Override
557                public CssMetaData<WebView, Number> getCssMetaData() {
558                    return StyleableProperties.PREF_HEIGHT;
559                }
560                @Override
561                public Object getBean() {
562                    return WebView.this;
563                }
564                @Override
565                public String getName() {
566                    return "prefHeight";
567                }
568            };
569        }
570        return prefHeight;
571    }
572    private DoubleProperty prefHeight;
573    
574    /**
575     * Sets preferred height.
576     */
577    public final void setPrefHeight(double value) {
578        prefHeightProperty().set(value);
579        _setHeight(handle, value);
580    }
581    
582    /**
583     * Returns preferred height.
584     */
585    public final double getPrefHeight() {
586        return (this.prefHeight != null)
587                ? this.prefHeight.get()
588                : DEFAULT_PREF_HEIGHT;
589    }
590
591    /**
592     * Convenience method for setting preferred width and height.
593     */
594    public void setPrefSize(double prefWidth, double prefHeight) {
595        setPrefWidth(prefWidth);
596        setPrefHeight(prefHeight);
597        _setWidth(handle, prefWidth);
598        _setHeight(handle, prefHeight);
599    }
600
601    /**
602     * Maximum width property.
603     */
604    public DoubleProperty maxWidthProperty() {
605        if (maxWidth == null) {
606            maxWidth = new StyleableDoubleProperty(DEFAULT_MAX_WIDTH) {
607                @Override
608                public void invalidated() {
609                    if (getParent() != null) {
610                        getParent().requestLayout();
611                    }
612                }
613                @Override
614                public CssMetaData<WebView, Number> getCssMetaData() {
615                    return StyleableProperties.MAX_WIDTH;
616                }
617                @Override
618                public Object getBean() {
619                    return WebView.this;
620                }
621                @Override
622                public String getName() {
623                    return "maxWidth";
624                }
625            };
626        }
627        return maxWidth;
628    }
629    private DoubleProperty maxWidth;
630    
631    /**
632     * Sets maximum width.
633     */
634    public final void setMaxWidth(double value) {
635        maxWidthProperty().set(value);
636        _setWidth(handle, value);
637    }
638    
639    /**
640     * Returns maximum width.
641     */
642    public final double getMaxWidth() {
643        return (this.maxWidth != null)
644                ? this.maxWidth.get()
645                : DEFAULT_MAX_WIDTH;
646    }
647
648    /**
649     * Maximum height property.
650     */
651    public DoubleProperty maxHeightProperty() {
652        if (maxHeight == null) {
653            maxHeight = new StyleableDoubleProperty(DEFAULT_MAX_HEIGHT) {
654                @Override
655                public void invalidated() {
656                    if (getParent() != null) {
657                        getParent().requestLayout();
658                    }
659                }
660                @Override
661                public CssMetaData<WebView, Number> getCssMetaData() {
662                    return StyleableProperties.MAX_HEIGHT;
663                }
664                @Override
665                public Object getBean() {
666                    return WebView.this;
667                }
668                @Override
669                public String getName() {
670                    return "maxHeight";
671                }
672            };
673        }
674        return maxHeight;
675    }
676    private DoubleProperty maxHeight;
677    
678    /**
679     * Sets maximum height.
680     */
681    public final void setMaxHeight(double value) {
682        maxHeightProperty().set(value);
683        _setHeight(handle, value);
684    }
685    
686    /**
687     * Returns maximum height.
688     */
689    public final double getMaxHeight() {
690        return (this.maxHeight != null)
691                ? this.maxHeight.get()
692                : DEFAULT_MAX_HEIGHT;
693    }
694
695    /**
696     * Convenience method for setting maximum width and height.
697     */
698    public void setMaxSize(double maxWidth, double maxHeight) {
699        setMaxWidth(maxWidth);
700        setMaxHeight(maxHeight);
701        _setWidth(handle, maxWidth);
702        _setHeight(handle, maxHeight);
703    }
704    
705    /**
706     * Specifies a requested font smoothing type : gray or LCD.
707     *
708     * The width of the bounding box is defined by the widest row.
709     *
710     * Note: LCD mode doesn't apply in numerous cases, such as various
711     * compositing modes, where effects are applied and very large glyphs.
712     *
713     * @defaultValue FontSmoothingType.LCD
714     * @since 2.2
715     */
716    private ObjectProperty<FontSmoothingType> fontSmoothingType;
717
718    public final void setFontSmoothingType(FontSmoothingType value) {
719        fontSmoothingTypeProperty().set(value);
720    }
721    
722    public final FontSmoothingType getFontSmoothingType() {
723        return (this.fontSmoothingType != null)
724                ? this.fontSmoothingType.get()
725                : DEFAULT_FONT_SMOOTHING_TYPE;
726    }
727
728    public final ObjectProperty<FontSmoothingType> fontSmoothingTypeProperty() {
729        if (this.fontSmoothingType == null) {
730            this.fontSmoothingType = new StyleableObjectProperty<FontSmoothingType>(DEFAULT_FONT_SMOOTHING_TYPE) {
731                @Override
732                public void invalidated() {
733                    Toolkit.getToolkit().checkFxUserThread();
734                }
735                @Override
736                public CssMetaData<WebView, FontSmoothingType> getCssMetaData() {
737                    return StyleableProperties.FONT_SMOOTHING_TYPE;
738                }
739                @Override
740                public Object getBean() {
741                    return WebView.this;
742                }
743                @Override
744                public String getName() {
745                    return "fontSmoothingType";
746                }
747            };
748        }
749        return this.fontSmoothingType;
750    }
751
752    /**
753     * Specifies whether context menu is enabled.
754     *
755     * @defaultValue true
756     * @since 2.2
757     */
758    private BooleanProperty contextMenuEnabled;
759
760    public final void setContextMenuEnabled(boolean value) {
761        contextMenuEnabledProperty().set(value);
762    }
763
764    public final boolean isContextMenuEnabled() {
765        return contextMenuEnabled == null
766                ? DEFAULT_CONTEXT_MENU_ENABLED
767                : contextMenuEnabled.get();
768    }
769
770    public final BooleanProperty contextMenuEnabledProperty() {
771        if (contextMenuEnabled == null) {
772            contextMenuEnabled = new StyleableBooleanProperty(DEFAULT_CONTEXT_MENU_ENABLED) {
773                @Override public void invalidated() {
774                    Toolkit.getToolkit().checkFxUserThread();
775                }
776
777                @Override public CssMetaData<WebView, Boolean> getCssMetaData() {
778                    return StyleableProperties.CONTEXT_MENU_ENABLED;
779                }
780
781                @Override public Object getBean() {
782                    return WebView.this;
783                }
784
785                @Override public String getName() {
786                    return "contextMenuEnabled";
787                }
788            };
789        }
790        return contextMenuEnabled;
791    }
792    
793    /**
794     * Super-lazy instantiation pattern from Bill Pugh.
795     */
796    private static final class StyleableProperties {
797
798        private static final CssMetaData<WebView, Boolean> CONTEXT_MENU_ENABLED
799                = new CssMetaData<WebView, Boolean>(
800                "-fx-context-menu-enabled",
801                BooleanConverter.getInstance(),
802                DEFAULT_CONTEXT_MENU_ENABLED)
803        {
804            @Override public boolean isSettable(WebView view) {
805                return view.contextMenuEnabled == null || !view.contextMenuEnabled.isBound();
806            }
807            @Override public StyleableProperty<Boolean> getStyleableProperty(WebView view) {
808                return (StyleableProperty<Boolean>)view.contextMenuEnabledProperty();
809            }
810        };
811
812        private static final CssMetaData<WebView, FontSmoothingType> FONT_SMOOTHING_TYPE
813                = new CssMetaData<WebView, FontSmoothingType>(
814                "-fx-font-smoothing-type",
815                new EnumConverter<FontSmoothingType>(FontSmoothingType.class),
816                DEFAULT_FONT_SMOOTHING_TYPE) {
817            @Override
818            public boolean isSettable(WebView view) {
819                return view.fontSmoothingType == null || !view.fontSmoothingType.isBound();
820            }
821            @Override
822            public StyleableProperty<FontSmoothingType> getStyleableProperty(WebView view) {
823                return (StyleableProperty<FontSmoothingType>)view.fontSmoothingTypeProperty();
824            }
825        };
826
827        private static final CssMetaData<WebView, Number> ZOOM
828                = new CssMetaData<WebView, Number>(
829                "-fx-zoom",
830                SizeConverter.getInstance(),
831                DEFAULT_ZOOM) {
832            @Override public boolean isSettable(WebView view) {
833                return view.zoom == null || !view.zoom.isBound();
834            }
835            @Override public StyleableProperty<Number> getStyleableProperty(WebView view) {
836                return (StyleableProperty<Number>)view.zoomProperty();
837            }
838        };
839
840        private static final CssMetaData<WebView, Number> FONT_SCALE
841                = new CssMetaData<WebView, Number>(
842                "-fx-font-scale",
843                SizeConverter.getInstance(),
844                DEFAULT_FONT_SCALE) {
845            @Override
846            public boolean isSettable(WebView view) {
847                return view.fontScale == null || !view.fontScale.isBound();
848            }
849            @Override
850            public StyleableProperty<Number> getStyleableProperty(WebView view) {
851                return (StyleableProperty<Number>)view.fontScaleProperty();
852            }
853        };
854
855        private static final CssMetaData<WebView, Number> MIN_WIDTH
856                = new CssMetaData<WebView, Number>(
857                "-fx-min-width",
858                SizeConverter.getInstance(),
859                DEFAULT_MIN_WIDTH) {
860            @Override
861            public boolean isSettable(WebView view) {
862                return view.minWidth == null || !view.minWidth.isBound();
863            }
864            @Override
865            public StyleableProperty<Number> getStyleableProperty(WebView view) {
866                return (StyleableProperty<Number>)view.minWidthProperty();
867            }
868        };
869
870        private static final CssMetaData<WebView, Number> MIN_HEIGHT
871                = new CssMetaData<WebView, Number>(
872                "-fx-min-height",
873                SizeConverter.getInstance(),
874                DEFAULT_MIN_HEIGHT) {
875            @Override
876            public boolean isSettable(WebView view) {
877                return view.minHeight == null || !view.minHeight.isBound();
878            }
879            @Override
880            public StyleableProperty<Number> getStyleableProperty(WebView view) {
881                return (StyleableProperty<Number>)view.minHeightProperty();
882            }
883        };
884
885        private static final CssMetaData<WebView, Number> MAX_WIDTH
886                = new CssMetaData<WebView, Number>(
887                "-fx-max-width",
888                SizeConverter.getInstance(),
889                DEFAULT_MAX_WIDTH) {
890            @Override
891            public boolean isSettable(WebView view) {
892                return view.maxWidth == null || !view.maxWidth.isBound();
893            }
894            @Override
895            public StyleableProperty<Number> getStyleableProperty(WebView view) {
896                return (StyleableProperty<Number>)view.maxWidthProperty();
897            }
898        };
899
900        private static final CssMetaData<WebView, Number> MAX_HEIGHT
901                = new CssMetaData<WebView, Number>(
902                "-fx-max-height",
903                SizeConverter.getInstance(),
904                DEFAULT_MAX_HEIGHT) {
905            @Override
906            public boolean isSettable(WebView view) {
907                return view.maxHeight == null || !view.maxHeight.isBound();
908            }
909            @Override
910            public StyleableProperty<Number> getStyleableProperty(WebView view) {
911                return (StyleableProperty<Number>)view.maxHeightProperty();
912            }
913        };
914
915        private static final CssMetaData<WebView, Number> PREF_WIDTH
916                = new CssMetaData<WebView, Number>(
917                "-fx-pref-width",
918                SizeConverter.getInstance(),
919                DEFAULT_PREF_WIDTH) {
920            @Override
921            public boolean isSettable(WebView view) {
922                return view.prefWidth == null || !view.prefWidth.isBound();
923            }
924            @Override
925            public StyleableProperty<Number> getStyleableProperty(WebView view) {
926                return (StyleableProperty<Number>)view.prefWidthProperty();
927            }
928        };
929
930        private static final CssMetaData<WebView, Number> PREF_HEIGHT
931                = new CssMetaData<WebView, Number>(
932                "-fx-pref-height",
933                SizeConverter.getInstance(),
934                DEFAULT_PREF_HEIGHT) {
935            @Override
936            public boolean isSettable(WebView view) {
937                return view.prefHeight == null || !view.prefHeight.isBound();
938            }
939            @Override
940            public StyleableProperty<Number> getStyleableProperty(WebView view) {
941                return (StyleableProperty<Number>)view.prefHeightProperty();
942            }
943        };
944
945        private static final List<CssMetaData<? extends Styleable, ?>> STYLEABLES;
946
947        static {
948            List<CssMetaData<? extends Styleable, ?>> styleables
949                    = new ArrayList<CssMetaData<? extends Styleable, ?>>(Parent.getClassCssMetaData());
950            styleables.add(CONTEXT_MENU_ENABLED);
951            styleables.add(FONT_SMOOTHING_TYPE);
952            styleables.add(ZOOM);
953            styleables.add(FONT_SCALE);
954            styleables.add(MIN_WIDTH);
955            styleables.add(PREF_WIDTH);
956            styleables.add(MAX_WIDTH);
957            styleables.add(MIN_HEIGHT);
958            styleables.add(PREF_HEIGHT);
959            styleables.add(MAX_HEIGHT);
960            STYLEABLES = Collections.unmodifiableList(styleables);
961         }
962    }
963
964    /**
965     * @return The CssMetaData associated with this class, which may include the
966     * CssMetaData of its super classes.
967     */
968    public static List<CssMetaData<? extends Styleable, ?>> getClassCssMetaData() {
969        return StyleableProperties.STYLEABLES;
970    }
971
972    /**
973     * {@inheritDoc}
974     */
975    @Override
976    public List<CssMetaData<? extends Styleable, ?>> getCssMetaData() {
977        return getClassCssMetaData();
978    }
979    
980    // event handling
981
982    private void handleStagePulse() {
983        // The stage pulse occurs before the scene pulse.
984        // Here the page content is updated before CSS/Layout/Sync pass
985        // is initiated by the scene pulse. The update may
986        // change the WebView children and, if so, the children should be
987        // processed right away during the scene pulse.
988
989        // The WebView node does not render its pending render queues
990        // while it is invisible. Therefore, we should not schedule new
991        // render queues while the WebView is invisible to prevent
992        // the list of render queues from growing infinitely.
993        // Also, if and when the WebView becomes invisible, the currently
994        // pending render queues, if any, become obsolete and should be
995        // discarded.
996
997        boolean reallyVisible = impl_isTreeVisible()
998                && getScene() != null
999                && getScene().getWindow() != null
1000                && getScene().getWindow().isShowing();
1001        
1002        if (reallyVisible) {
1003            if (impl_isDirty(DirtyBits.WEBVIEW_VIEW)) {
1004                Scene.impl_setAllowPGAccess(true);
1005                //getPGWebView().update(); // creates new render queues
1006                Scene.impl_setAllowPGAccess(false);
1007            }
1008        }
1009    }
1010
1011    /**
1012     * @treatasprivate implementation detail
1013     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1014     */
1015    @Deprecated
1016    @Override protected void impl_pickNodeLocal(PickRay pickRay, PickResultChooser result) {
1017        impl_intersects(pickRay, result);
1018    }
1019
1020    @Override protected ObservableList<Node> getChildren() {
1021        return super.getChildren();
1022    }
1023    
1024    // Node stuff
1025
1026    /**
1027     * @treatasprivate implementation detail
1028     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1029     */
1030//    @Deprecated
1031//    @Override protected PGNode impl_createPGNode() {
1032//        return ImplementationManager.createView(this);
1033//    }
1034
1035    /**
1036     * @treatasprivate implementation detail
1037     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1038     */
1039    @Deprecated
1040    @Override public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) {
1041        bounds.deriveWithNewBounds(0, 0, 0, (float) getWidth(), (float)getHeight(), 0);
1042        tx.transform(bounds, bounds);
1043        return bounds;
1044    }
1045
1046    /**
1047     * @treatasprivate implementation detail
1048     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1049     */
1050    @Deprecated
1051    @Override protected boolean impl_computeContains(double localX, double localY) {
1052        // Note: Local bounds contain test is already done by the caller. (Node.contains()).
1053        return true;
1054    }
1055
1056    /**
1057     * @treatasprivate implementation detail
1058     * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1059     */
1060    @Deprecated
1061    @Override public void impl_updatePG() {
1062        super.impl_updatePG();
1063        //PGWebView peer = getPGWebView();
1064        
1065        if (impl_isDirty(DirtyBits.NODE_GEOMETRY)) {
1066            //peer.resize((float)getWidth(), (float)getHeight());
1067        }
1068        if (impl_isDirty(DirtyBits.WEBVIEW_VIEW)) {
1069            //peer.requestRender();
1070        }
1071    }
1072    
1073    private static Affine3D calculateNodeToSceneTransform(Node node) {
1074        final Affine3D transform = new Affine3D();
1075        do {
1076            transform.preConcatenate(node.impl_getLeafTransform());
1077            node = node.getParent();
1078        } while (node != null);
1079        
1080        return transform;
1081    }
1082    
1083    @Deprecated
1084    @Override public void impl_transformsChanged() {
1085        super.impl_transformsChanged();
1086    
1087        Affine3D trans = calculateNodeToSceneTransform(this);
1088        _setTransform(handle,
1089                trans.getMxx(), trans.getMxy(), trans.getMxz(), trans.getMxt(),
1090                trans.getMyx(), trans.getMyy(), trans.getMyz(), trans.getMyt(),
1091                trans.getMzx(), trans.getMzy(), trans.getMzz(), trans.getMzt());
1092    }
1093    
1094    long getNativeHandle() {
1095        return handle;
1096    }
1097    
1098    
1099    // native callbacks
1100    private void notifyLoadStarted() {
1101        engine.notifyLoadStarted();
1102    }
1103    private void notifyLoadFinished() {
1104        engine.notifyLoadFinished();
1105    }
1106    private void notifyLoadFailed() {
1107        engine.notifyLoadFailed();
1108    }
1109    private void notifyJavaCall(String arg) {
1110        engine.notifyJavaCall(arg);
1111    }
1112    
1113    
1114    /* Inits native WebView and returns its pointer in the given array */
1115    private native void _initWebView(long[] nativeHandle);
1116    
1117    /* Sets width of the native WebView  */
1118    private native void _setWidth(long handle, double w);
1119    
1120    /* Sets height of the native WebView  */
1121    private native void _setHeight(long handle, double h);
1122    
1123    /* Sets visibility of the native WebView  */
1124    private native void _setVisible(long handle, boolean v);
1125    
1126    /* Removes the native WebView from scene */
1127    private native void _removeWebView(long handle);
1128    
1129    /* Applies transform on the native WebView  */
1130    private native void _setTransform(long handle,
1131            double mxx, double mxy, double mxz, double mxt,
1132            double myx, double myy, double myz, double myt,
1133            double mzx, double mzy, double mzz, double mzt);
1134}