293 WCFocusEvent.UNKNOWN);
294 page.dispatchFocusEvent(focusEvent);
295 }
296 });
297 setFocusTraversable(true);
298 Toolkit.getToolkit().addStageTkPulseListener(stagePulseListener);
299 }
300
301 // Resizing support. Allows arbitrary growing and shrinking.
302 // Designed after javafx.scene.control.Control
303
304 @Override public boolean isResizable() {
305 return true;
306 }
307
308 @Override public void resize(double width, double height) {
309 if ((width != this.width.get()) || (height != this.height.get())) {
310 this.width.set(width);
311 this.height.set(height);
312 NodeHelper.markDirty(this, DirtyBits.NODE_GEOMETRY);
313 impl_geomChanged();
314 }
315 }
316
317 /**
318 * Called during layout to determine the minimum width for this node.
319 *
320 * @return the minimum width that this node should be resized to during layout
321 */
322 @Override public final double minWidth(double height) {
323 final double result = getMinWidth();
324 return Double.isNaN(result) || result < 0 ? 0 : result;
325 }
326
327 /**
328 * Called during layout to determine the minimum height for this node.
329 *
330 * @return the minimum height that this node should be resized to during layout
331 */
332 @Override public final double minHeight(double width) {
333 final double result = getMinHeight();
954 return getClassCssMetaData();
955 }
956
957 // event handling
958
959 // To handle stage pulse we need to know if currently webview and
960 // tree is visible or not
961 private boolean isTreeReallyVisible() {
962 if (getScene() == null) {
963 return false;
964 }
965
966 final Window window = getScene().getWindow();
967
968 if (window == null) {
969 return false;
970 }
971
972 boolean iconified = (window instanceof Stage) ? ((Stage)window).isIconified() : false;
973
974 return impl_isTreeVisible()
975 && window.isShowing()
976 && window.getWidth() > 0
977 && window.getHeight() > 0
978 && !iconified;
979 }
980
981 private void handleStagePulse() {
982 // The stage pulse occurs before the scene pulse.
983 // Here the page content is updated before CSS/Layout/Sync pass
984 // is initiated by the scene pulse. The update may
985 // change the WebView children and, if so, the children should be
986 // processed right away during the scene pulse.
987
988 // The WebView node does not render its pending render queues
989 // while it is invisible. Therefore, we should not schedule new
990 // render queues while the WebView is invisible to prevent
991 // the list of render queues from growing infinitely.
992 // Also, if and when the WebView becomes invisible, the currently
993 // pending render queues, if any, become obsolete and should be
994 // discarded.
1232 //Drag source implementation:
1233 setOnDragDetected(event -> {
1234 if (page.isDragConfirmed()) {
1235 page.confirmStartDrag();
1236 event.consume();
1237 }
1238 });
1239 setOnDragDone(event -> {
1240 page.dispatchDragOperation(
1241 WebPage.DND_SRC_DROP,
1242 null, null,
1243 (int)event.getX(), (int)event.getY(),
1244 (int)event.getScreenX(), (int)event.getScreenY(),
1245 getWKDndAction(event.getAcceptedTransferMode()));
1246 event.consume();
1247 });
1248
1249 setInputMethodRequests(getInputMethodClient());
1250 }
1251
1252 /**
1253 * @treatAsPrivate implementation detail
1254 * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1255 */
1256 @Deprecated
1257 @Override protected void impl_pickNodeLocal(PickRay pickRay, PickResultChooser result) {
1258 impl_intersects(pickRay, result);
1259 }
1260
1261 @Override protected ObservableList<Node> getChildren() {
1262 return super.getChildren();
1263 }
1264
1265 // Node stuff
1266
1267 /*
1268 * Note: This method MUST only be called via its accessor method.
1269 */
1270 private NGNode doCreatePeer() {
1271 return new NGWebView();
1272 }
1273
1274 /**
1275 * @treatAsPrivate implementation detail
1276 * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1277 */
1278 @Deprecated
1279 @Override public BaseBounds impl_computeGeomBounds(BaseBounds bounds, BaseTransform tx) {
1280 bounds.deriveWithNewBounds(0, 0, 0, (float) getWidth(), (float)getHeight(), 0);
1281 tx.transform(bounds, bounds);
1282 return bounds;
1283 }
1284
1285 /**
1286 * @treatAsPrivate implementation detail
1287 * @deprecated This is an internal API that is not intended for use and will be removed in the next version
1288 */
1289 @Deprecated
1290 @Override protected boolean impl_computeContains(double localX, double localY) {
1291 // Note: Local bounds contain test is already done by the caller. (Node.contains()).
1292 return true;
1293 }
1294
1295 /*
1296 * Note: This method MUST only be called via its accessor method.
1297 */
1298 private void doUpdatePeer() {
1299 final NGWebView peer = NodeHelper.getPeer(this);
1300
1301 if (NodeHelper.isDirty(this, DirtyBits.NODE_CONTENTS)) {
1302 peer.setPage(page);
1303 }
1304 if (NodeHelper.isDirty(this, DirtyBits.NODE_GEOMETRY)) {
1305 peer.resize((float)getWidth(), (float)getHeight());
1306 }
1307 if (NodeHelper.isDirty(this, DirtyBits.WEBVIEW_VIEW)) {
1308 peer.requestRender();
1309 }
1310 }
1311
1312 static {
1313 WebViewHelper.setWebViewAccessor(new WebViewHelper.WebViewAccessor() {
1314 @Override
1315 public NGNode doCreatePeer(Node node) {
1316 return ((WebView) node).doCreatePeer();
1317 }
1318
1319 @Override
1320 public void doUpdatePeer(Node node) {
1321 ((WebView) node).doUpdatePeer();
1322 }
1323 });
1324
1325 idMap.put(MouseButton.NONE, WCMouseEvent.NOBUTTON);
1326 idMap.put(MouseButton.PRIMARY, WCMouseEvent.BUTTON1);
1327 idMap.put(MouseButton.MIDDLE, WCMouseEvent.BUTTON2);
1328 idMap.put(MouseButton.SECONDARY, WCMouseEvent.BUTTON3);
1329
1330 idMap.put(MouseEvent.MOUSE_PRESSED, WCMouseEvent.MOUSE_PRESSED);
1331 idMap.put(MouseEvent.MOUSE_RELEASED, WCMouseEvent.MOUSE_RELEASED);
1332 idMap.put(MouseEvent.MOUSE_MOVED, WCMouseEvent.MOUSE_MOVED);
1333 idMap.put(MouseEvent.MOUSE_DRAGGED, WCMouseEvent.MOUSE_DRAGGED);
1334
1335 idMap.put(KeyEvent.KEY_PRESSED, WCKeyEvent.KEY_PRESSED);
1336 idMap.put(KeyEvent.KEY_RELEASED, WCKeyEvent.KEY_RELEASED);
1337 idMap.put(KeyEvent.KEY_TYPED, WCKeyEvent.KEY_TYPED);
1338 }
1339 }
|
293 WCFocusEvent.UNKNOWN);
294 page.dispatchFocusEvent(focusEvent);
295 }
296 });
297 setFocusTraversable(true);
298 Toolkit.getToolkit().addStageTkPulseListener(stagePulseListener);
299 }
300
301 // Resizing support. Allows arbitrary growing and shrinking.
302 // Designed after javafx.scene.control.Control
303
304 @Override public boolean isResizable() {
305 return true;
306 }
307
308 @Override public void resize(double width, double height) {
309 if ((width != this.width.get()) || (height != this.height.get())) {
310 this.width.set(width);
311 this.height.set(height);
312 NodeHelper.markDirty(this, DirtyBits.NODE_GEOMETRY);
313 NodeHelper.geomChanged(this);
314 }
315 }
316
317 /**
318 * Called during layout to determine the minimum width for this node.
319 *
320 * @return the minimum width that this node should be resized to during layout
321 */
322 @Override public final double minWidth(double height) {
323 final double result = getMinWidth();
324 return Double.isNaN(result) || result < 0 ? 0 : result;
325 }
326
327 /**
328 * Called during layout to determine the minimum height for this node.
329 *
330 * @return the minimum height that this node should be resized to during layout
331 */
332 @Override public final double minHeight(double width) {
333 final double result = getMinHeight();
954 return getClassCssMetaData();
955 }
956
957 // event handling
958
959 // To handle stage pulse we need to know if currently webview and
960 // tree is visible or not
961 private boolean isTreeReallyVisible() {
962 if (getScene() == null) {
963 return false;
964 }
965
966 final Window window = getScene().getWindow();
967
968 if (window == null) {
969 return false;
970 }
971
972 boolean iconified = (window instanceof Stage) ? ((Stage)window).isIconified() : false;
973
974 return NodeHelper.isTreeVisible(this)
975 && window.isShowing()
976 && window.getWidth() > 0
977 && window.getHeight() > 0
978 && !iconified;
979 }
980
981 private void handleStagePulse() {
982 // The stage pulse occurs before the scene pulse.
983 // Here the page content is updated before CSS/Layout/Sync pass
984 // is initiated by the scene pulse. The update may
985 // change the WebView children and, if so, the children should be
986 // processed right away during the scene pulse.
987
988 // The WebView node does not render its pending render queues
989 // while it is invisible. Therefore, we should not schedule new
990 // render queues while the WebView is invisible to prevent
991 // the list of render queues from growing infinitely.
992 // Also, if and when the WebView becomes invisible, the currently
993 // pending render queues, if any, become obsolete and should be
994 // discarded.
1232 //Drag source implementation:
1233 setOnDragDetected(event -> {
1234 if (page.isDragConfirmed()) {
1235 page.confirmStartDrag();
1236 event.consume();
1237 }
1238 });
1239 setOnDragDone(event -> {
1240 page.dispatchDragOperation(
1241 WebPage.DND_SRC_DROP,
1242 null, null,
1243 (int)event.getX(), (int)event.getY(),
1244 (int)event.getScreenX(), (int)event.getScreenY(),
1245 getWKDndAction(event.getAcceptedTransferMode()));
1246 event.consume();
1247 });
1248
1249 setInputMethodRequests(getInputMethodClient());
1250 }
1251
1252 /*
1253 * Note: This method MUST only be called via its accessor method.
1254 */
1255 private void doPickNodeLocal(PickRay pickRay, PickResultChooser result) {
1256 NodeHelper.intersects(this, pickRay, result);
1257 }
1258
1259 @Override protected ObservableList<Node> getChildren() {
1260 return super.getChildren();
1261 }
1262
1263 // Node stuff
1264
1265 /*
1266 * Note: This method MUST only be called via its accessor method.
1267 */
1268 private NGNode doCreatePeer() {
1269 return new NGWebView();
1270 }
1271
1272 /*
1273 * Note: This method MUST only be called via its accessor method.
1274 */
1275 private BaseBounds doComputeGeomBounds(BaseBounds bounds, BaseTransform tx) {
1276 bounds.deriveWithNewBounds(0, 0, 0, (float) getWidth(), (float)getHeight(), 0);
1277 tx.transform(bounds, bounds);
1278 return bounds;
1279 }
1280
1281 /*
1282 * Note: This method MUST only be called via its accessor method.
1283 */
1284 private void doTransformsChanged() {
1285 }
1286
1287 /*
1288 * Note: This method MUST only be called via its accessor method.
1289 */
1290 private boolean doComputeContains(double localX, double localY) {
1291 // Note: Local bounds contain test is already done by the caller. (Node.contains()).
1292 return true;
1293 }
1294
1295 /*
1296 * Note: This method MUST only be called via its accessor method.
1297 */
1298 private void doUpdatePeer() {
1299 final NGWebView peer = NodeHelper.getPeer(this);
1300
1301 if (NodeHelper.isDirty(this, DirtyBits.NODE_CONTENTS)) {
1302 peer.setPage(page);
1303 }
1304 if (NodeHelper.isDirty(this, DirtyBits.NODE_GEOMETRY)) {
1305 peer.resize((float)getWidth(), (float)getHeight());
1306 }
1307 if (NodeHelper.isDirty(this, DirtyBits.WEBVIEW_VIEW)) {
1308 peer.requestRender();
1309 }
1310 }
1311
1312 static {
1313 WebViewHelper.setWebViewAccessor(new WebViewHelper.WebViewAccessor() {
1314 @Override
1315 public NGNode doCreatePeer(Node node) {
1316 return ((WebView) node).doCreatePeer();
1317 }
1318
1319 @Override
1320 public void doUpdatePeer(Node node) {
1321 ((WebView) node).doUpdatePeer();
1322 }
1323
1324 @Override
1325 public void doTransformsChanged(Node node) {
1326 ((WebView) node).doTransformsChanged();
1327 }
1328
1329 @Override
1330 public BaseBounds doComputeGeomBounds(Node node,
1331 BaseBounds bounds, BaseTransform tx) {
1332 return ((WebView) node).doComputeGeomBounds(bounds, tx);
1333 }
1334
1335 @Override
1336 public boolean doComputeContains(Node node, double localX, double localY) {
1337 return ((WebView) node).doComputeContains(localX, localY);
1338 }
1339
1340 @Override
1341 public void doPickNodeLocal(Node node, PickRay localPickRay,
1342 PickResultChooser result) {
1343 ((WebView) node).doPickNodeLocal(localPickRay, result);
1344 }
1345 });
1346
1347 idMap.put(MouseButton.NONE, WCMouseEvent.NOBUTTON);
1348 idMap.put(MouseButton.PRIMARY, WCMouseEvent.BUTTON1);
1349 idMap.put(MouseButton.MIDDLE, WCMouseEvent.BUTTON2);
1350 idMap.put(MouseButton.SECONDARY, WCMouseEvent.BUTTON3);
1351
1352 idMap.put(MouseEvent.MOUSE_PRESSED, WCMouseEvent.MOUSE_PRESSED);
1353 idMap.put(MouseEvent.MOUSE_RELEASED, WCMouseEvent.MOUSE_RELEASED);
1354 idMap.put(MouseEvent.MOUSE_MOVED, WCMouseEvent.MOUSE_MOVED);
1355 idMap.put(MouseEvent.MOUSE_DRAGGED, WCMouseEvent.MOUSE_DRAGGED);
1356
1357 idMap.put(KeyEvent.KEY_PRESSED, WCKeyEvent.KEY_PRESSED);
1358 idMap.put(KeyEvent.KEY_RELEASED, WCKeyEvent.KEY_RELEASED);
1359 idMap.put(KeyEvent.KEY_TYPED, WCKeyEvent.KEY_TYPED);
1360 }
1361 }
|