source: trunk/src/org/expeditee/items/widgets/JfxBrowser.java@ 815

Last change on this file since 815 was 815, checked in by jts21, 10 years ago

Add ability to extract images from a web browser by right clicking them

  • Property svn:executable set to *
File size: 23.8 KB
Line 
1package org.expeditee.items.widgets;
2
3/*
4 * JavaFX is not on the default java classpath until Java 8 (but is still included with Java 7), so your IDE will probably complain that the imports below can't be resolved.
5 * In Eclipse hitting'Proceed' when told 'Errors exist in project' should allow you to run Expeditee without any issues (although the JFX Browser widget will not display),
6 * or you can just exclude JfxBrowser, WebParser and JfxbrowserActions from the build path.
7 *
8 * If you are using Ant to build/run, 'ant build' will try to build with JavaFX jar added to the classpath.
9 * If this fails, 'ant build-nojfx' will build with the JfxBrowser, WebParser and JfxbrowserActions excluded from the build path.
10 */
11import java.awt.Point;
12import java.lang.reflect.Field;
13
14import javafx.application.Platform;
15import javafx.beans.value.ChangeListener;
16import javafx.beans.value.ObservableValue;
17import javafx.concurrent.Worker.State;
18import javafx.embed.swing.JFXPanel;
19import javafx.event.ActionEvent;
20import javafx.event.Event;
21import javafx.event.EventDispatchChain;
22import javafx.event.EventDispatcher;
23import javafx.event.EventHandler;
24import javafx.geometry.Point2D;
25import javafx.geometry.Rectangle2D;
26import javafx.scene.Node;
27import javafx.scene.Scene;
28import javafx.scene.control.Button;
29import javafx.scene.control.TextField;
30import javafx.scene.input.KeyEvent;
31import javafx.scene.input.MouseButton;
32import javafx.scene.input.MouseEvent;
33import javafx.scene.layout.HBox;
34import javafx.scene.layout.Priority;
35import javafx.scene.layout.VBox;
36import javafx.scene.web.WebEngine;
37import javafx.scene.web.WebView;
38import netscape.javascript.JSObject;
39
40import org.expeditee.gui.DisplayIO;
41import org.expeditee.gui.FrameMouseActions;
42import org.expeditee.gui.FreeItems;
43import org.expeditee.gui.MessageBay;
44import org.expeditee.io.WebParser;
45import org.expeditee.items.Item;
46import org.expeditee.items.Picture;
47import org.expeditee.items.Text;
48import org.expeditee.settings.network.NetworkSettings;
49
50import com.sun.javafx.scene.control.skin.TextFieldSkin;
51import com.sun.javafx.scene.text.HitInfo;
52
53/**
54 * Web browser using a JavaFX WebView.
55 *
56 * @author ngw8
57 * @author jts21
58 */
59public class JfxBrowser extends DataFrameWidget {
60
61 private static final String BACK = "back";
62 private static final String FORWARD = "forward";
63 private static final String REFRESH = "refresh";
64 private static final String CONVERT = "convert";
65
66 private JFXPanel _panel;
67 private WebView _webView;
68 private WebEngine _webEngine;
69 private TextField _urlField;
70
71 private MouseButton _buttonDownId = MouseButton.NONE;
72 private MouseEvent _backupEvent = null;
73 private static Field MouseEvent_x, MouseEvent_y;
74
75 static {
76 Platform.setImplicitExit(false);
77
78 try {
79 MouseEvent_x = MouseEvent.class.getDeclaredField("x");
80 MouseEvent_x.setAccessible(true);
81 MouseEvent_y = MouseEvent.class.getDeclaredField("y");
82 MouseEvent_y.setAccessible(true);
83 } catch (Exception e) {
84 e.printStackTrace();
85 }
86 }
87
88 private Point getCoordFromCaret(TextField text) {
89 TextFieldSkin skin = (TextFieldSkin) text.getSkin();
90
91 Point2D onScene = text.localToScene(0, 0);
92
93 double x = onScene.getX() + JfxBrowser.this.getX();// - org.expeditee.gui.Browser._theBrowser.getOrigin().x;
94 double y = onScene.getY() + JfxBrowser.this.getY();// - org.expeditee.gui.Browser._theBrowser.getOrigin().y;
95
96 Rectangle2D cp = skin.getCharacterBounds(text.getCaretPosition());
97
98 return new Point((int) (cp.getMinX() + x), (int) (cp.getMinY() + y));
99 }
100
101 private int getCaretFromCoord(TextField text, MouseEvent e) {
102 TextFieldSkin skin = (TextFieldSkin) text.getSkin();
103 HitInfo hit = skin.getIndex(e);
104 return hit.getInsertionIndex();
105 }
106
107 /**
108 * @param src The MouseEvent to clone
109 * @param node The node the position will be relative to
110 * @param x The position in Expeditee space
111 * @param y The position in Expeditee space
112 * @return A fake MouseEvent for a specific position relative to a Node
113 */
114 private MouseEvent getMouseEventForPosition(MouseEvent src, Node node, int x, int y) {
115 MouseEvent dst = (MouseEvent) ((Event) src).copyFor(null, null);
116 try {
117 MouseEvent_x.set(dst, x - node.localToScene(0, 0).getX());
118 MouseEvent_y.set(dst, y - node.localToScene(0, 0).getY());
119 } catch (Exception e) {
120 e.printStackTrace();
121 }
122 return dst;
123 }
124
125 public JfxBrowser(Text source, final String[] args) {
126 // Initial page is either the page stored in the arguments (if there is one stored) or the homepage
127 super(source, new JFXPanel(), -1, 500, -1, -1, 300, -1);
128
129 _panel = (JFXPanel) _swingComponent;
130
131 Platform.runLater(new Runnable() {
132 @Override
133 public void run() {
134 initFx((args != null && args.length > 0) ? args[0] : NetworkSettings.HomePage.get());
135 }
136 });
137 }
138
139 /**
140 * Sets up the browser frame. JFX requires this to be run on a new thread.
141 *
142 * @param url
143 * The URL to be loaded when the browser is created
144 */
145 private void initFx(String url) {
146 try {
147 VBox vertical = new VBox();
148 HBox horizontal = new HBox();
149
150 Button backButton = new Button("Back");
151 backButton.setMinWidth(Button.USE_PREF_SIZE);
152 backButton.setFocusTraversable(false);
153 Button forwardButton = new Button("Forward");
154 forwardButton.setMinWidth(Button.USE_PREF_SIZE);
155 forwardButton.setFocusTraversable(false);
156 this._urlField = new TextField(url);
157 this._urlField.setMinWidth(0);
158 this._urlField.setMaxWidth(Double.MAX_VALUE);
159 this._urlField.setFocusTraversable(false);
160 Button convertButton = new Button("Convert");
161 convertButton.setMinWidth(Button.USE_PREF_SIZE);
162 convertButton.setFocusTraversable(false);
163 Button convertButtonNew = new Button("Convert (New Method)");
164 convertButtonNew.setMinWidth(Button.USE_PREF_SIZE);
165 convertButtonNew.setFocusTraversable(false);
166
167 horizontal.getChildren().addAll(backButton, forwardButton, this._urlField, convertButton, convertButtonNew);
168
169 HBox.setHgrow(backButton, Priority.NEVER);
170 HBox.setHgrow(forwardButton, Priority.NEVER);
171 HBox.setHgrow(convertButton, Priority.NEVER);
172 HBox.setHgrow(convertButtonNew, Priority.NEVER);
173 HBox.setHgrow(this._urlField, Priority.ALWAYS);
174
175 this._webView = new WebView();
176 this._webView.setMaxWidth(Double.MAX_VALUE);
177 this._webView.setMaxHeight(Double.MAX_VALUE);
178 HBox.setHgrow(this._webView, Priority.ALWAYS);
179 VBox.setVgrow(this._webView, Priority.ALWAYS);
180 this._webEngine = this._webView.getEngine();
181
182 vertical.getChildren().addAll(horizontal, this._webView);
183
184 Scene scene = new Scene(vertical);
185
186 this._panel.setScene(scene);
187
188 // Disable right click menu
189 this._webView.setContextMenuEnabled(false);
190 final EventDispatcher initial = this._urlField.getEventDispatcher();
191 this._urlField.setEventDispatcher(new EventDispatcher() {
192 @Override
193 public Event dispatchEvent(Event e, EventDispatchChain tail) {
194 if (e instanceof MouseEvent) {
195 MouseEvent m = (MouseEvent) e;
196 if (m.getButton() == MouseButton.SECONDARY && m.getEventType() == MouseEvent.MOUSE_RELEASED) {
197 e.consume();
198 JfxBrowser.this._urlField.getOnMouseReleased().handle(m);
199 }
200 }
201 return initial.dispatchEvent(e, tail);
202 }
203 });
204
205 backButton.setOnAction(new EventHandler<ActionEvent>() {
206 @Override
207 public void handle(ActionEvent e) {
208 navigateBack();
209 }
210 });
211
212 forwardButton.setOnAction(new EventHandler<ActionEvent>() {
213 @Override
214 public void handle(ActionEvent e) {
215 navigateForward();
216 }
217 });
218
219
220 convertButton.setOnAction(new EventHandler<ActionEvent>() {
221 @Override
222 public void handle(ActionEvent e) {
223 getFrame();
224 }
225 });
226
227 convertButtonNew.setOnAction(new EventHandler<ActionEvent>() {
228 @Override
229 public void handle(ActionEvent e) {
230 getFrameNew();
231 }
232 });
233
234 this._urlField.setOnAction(new EventHandler<ActionEvent>() {
235 @Override
236 public void handle(ActionEvent e) {
237 navigate(JfxBrowser.this._urlField.getText());
238 }
239 });
240
241 this._urlField.setOnKeyTyped(new EventHandler<KeyEvent>() {
242 @Override
243 public void handle(KeyEvent e) {
244 // Hiding the cursor when typing, to be more Expeditee-like
245 DisplayIO.setCursor(org.expeditee.items.Item.HIDDEN_CURSOR);
246 }
247 });
248
249 this._urlField.setOnMouseMoved(new EventHandler<MouseEvent>() {
250 @Override
251 public void handle(MouseEvent e) {
252 JfxBrowser.this._backupEvent = e;
253 // make sure we have focus if the mouse is moving over us
254 if(!JfxBrowser.this._urlField.isFocused()) {
255 JfxBrowser.this._urlField.requestFocus();
256 }
257 // Checking if the user has been typing - if so, move the cursor to the caret position
258 if (DisplayIO.getCursor() == Item.HIDDEN_CURSOR) {
259 DisplayIO.setCursor(org.expeditee.items.Item.TEXT_CURSOR);
260 DisplayIO.setCursorPosition(getCoordFromCaret(JfxBrowser.this._urlField));
261 } else {
262 // Otherwise, move the caret to the cursor location
263 // int x = FrameMouseActions.getX() - JfxBrowser.this.getX(), y = FrameMouseActions.getY() - JfxBrowser.this.getY();
264 JfxBrowser.this._urlField.positionCaret(getCaretFromCoord(JfxBrowser.this._urlField, e));
265 }
266 }
267 });
268
269 this._urlField.setOnMouseEntered(new EventHandler<MouseEvent>() {
270 @Override
271 public void handle(MouseEvent arg0) {
272 JfxBrowser.this._urlField.requestFocus();
273 }
274 });
275
276 this._urlField.setOnMouseExited(new EventHandler<MouseEvent>() {
277 @Override
278 public void handle(MouseEvent arg0) {
279 JfxBrowser.this._webView.requestFocus();
280 }
281 });
282
283 this._urlField.setOnMouseDragged(new EventHandler<MouseEvent>() {
284 @Override
285 public void handle(MouseEvent e) {
286 TextFieldSkin skin = (TextFieldSkin) JfxBrowser.this._urlField.getSkin();
287
288 if (!JfxBrowser.this._urlField.isDisabled()) {
289 if (JfxBrowser.this._buttonDownId == MouseButton.MIDDLE || JfxBrowser.this._buttonDownId == MouseButton.SECONDARY) {
290 if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown())) {
291 skin.positionCaret(skin.getIndex(e), true);
292 }
293 }
294 }
295 }
296 });
297
298 this._urlField.focusedProperty().addListener(new ChangeListener<Boolean>() {
299 @Override
300 public void changed(ObservableValue<? extends Boolean> property, Boolean oldValue, Boolean newValue) {
301 if(newValue.booleanValue()) {
302 DisplayIO.setCursor(org.expeditee.items.Item.TEXT_CURSOR);
303 } else {
304 // Restoring the standard cursor, since it is changed to a text cursor when focus is gained
305 DisplayIO.setCursor(org.expeditee.items.Item.DEFAULT_CURSOR);
306 }
307 }
308 });
309
310 this._urlField.setOnMouseReleased(new EventHandler<MouseEvent>() {
311 @Override
312 public void handle(MouseEvent e) {
313 JfxBrowser.this._buttonDownId = MouseButton.NONE;
314
315 Text item;
316
317 // If nothing is selected, then select all the text so that it will be copied/moved
318 if (JfxBrowser.this._urlField.getSelectedText() == null || JfxBrowser.this._urlField.getSelectedText().length() == 0) {
319 JfxBrowser.this._urlField.selectAll();
320 }
321
322 if (e.getButton() == MouseButton.SECONDARY) {
323 // Right mouse button released, so copy the selection (i.e. don't remove the original)
324 item = DisplayIO.getCurrentFrame().createNewText(JfxBrowser.this._urlField.getSelectedText());
325 FrameMouseActions.pickup(item);
326 } else if (e.getButton() == MouseButton.MIDDLE) {
327 // Middle mouse button released, so copy the selection then remove it from the URL field
328 item = DisplayIO.getCurrentFrame().createNewText(JfxBrowser.this._urlField.getSelectedText());
329 JfxBrowser.this._urlField.setText(
330 JfxBrowser.this._urlField.getText().substring(0, JfxBrowser.this._urlField.getSelection().getStart())
331 + JfxBrowser.this._urlField.getText().substring(JfxBrowser.this._urlField.getSelection().getEnd(),
332 JfxBrowser.this._urlField.getText().length()));
333
334 FrameMouseActions.pickup(item);
335 }
336 }
337 });
338
339 this._urlField.setOnMousePressed(new EventHandler<MouseEvent>() {
340 @Override
341 public void handle(MouseEvent e) {
342 JfxBrowser.this._buttonDownId = e.getButton();
343 }
344 });
345
346 this._webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
347
348 @Override
349 public void changed(ObservableValue<? extends State> ov, State oldState, State newState) {
350
351 switch (newState) {
352 case READY: // READY
353 // MessageBay.displayMessage("WebEngine ready");
354 break;
355 case SCHEDULED: // SCHEDULED
356 // MessageBay.displayMessage("Scheduled page load");
357 break;
358 case RUNNING: // RUNNING
359 System.out.println("Loading page!");
360
361 // Updating the URL bar to display the URL of the page being loaded
362 JfxBrowser.this._urlField.setText(JfxBrowser.this._webEngine.getLocation());
363
364 break;
365 case SUCCEEDED: // SUCCEEDED
366 MessageBay.displayMessage("Finished loading page");
367 break;
368 case CANCELLED: // CANCELLED
369 MessageBay.displayMessage("Cancelled loading page");
370 break;
371 case FAILED: // FAILED
372 MessageBay.displayMessage("Failed to load page");
373 break;
374 }
375 }
376 });
377
378 // Captures mouse click events on webview to enable expeditee like behavior for JavaFX browser.
379 this._webView.setOnMouseClicked(new EventHandler<javafx.scene.input.MouseEvent>() {
380 @Override
381 public void handle(javafx.scene.input.MouseEvent e) {
382 if(e.getButton() == MouseButton.SECONDARY) {
383 // Gets text currently selected in webview
384 String selection = (String) JfxBrowser.this._webEngine.executeScript("window.getSelection().toString()");
385
386 // If no text is selected, see if an image is under the cursor
387 if (selection.length() == 0) {
388 JSObject window = (JSObject) JfxBrowser.this._webEngine.executeScript("window");
389 Object image = JfxBrowser.this._webEngine.executeScript(""
390 + "function isImage(o) {"
391 + " if(o.tagName == \"IMG\" && o.src != null) {"
392 + " return true;"
393 + " }"
394 + " if(window.getComputedStyle(o).getPropertyValue(\"background-image\").indexOf(\"url\") == 0) {"
395 + " return true;"
396 + " }"
397 + " return false;"
398 + "};"
399 + "var clicked = document.elementFromPoint(" + e.getX() + "," + e.getY() + ");"
400 + "if(isImage(clicked)) {"
401 + " clicked;"
402 + "} else {"
403 // TODO: look in child elements and other elements behind the current one
404 // For now just return nothing
405 + " null;"
406 + "}"
407 + "");
408 if(image instanceof org.w3c.dom.Node) {
409 System.out.println(image);
410 try {
411 JSObject style = (JSObject) window.call("getComputedStyle", image);
412
413 JSObject bounds = (JSObject) ((JSObject) image).call("getBoundingClientRect", new Object[] {});
414 float width = Float.valueOf(bounds.getMember("width").toString());
415 float height = Float.valueOf(bounds.getMember("height").toString());
416
417 Picture pic;
418
419 org.w3c.dom.Node node = ((org.w3c.dom.Node) image);
420
421 if (((String) style.call("getPropertyValue", new Object[] { "background-image" })).startsWith("url(")) {
422 pic = WebParser.getBackgroundImageFromNode(node, style, DisplayIO.getCurrentFrame(), null,
423 (float) FrameMouseActions.getX(), (float) FrameMouseActions.getY(), width, height);
424 } else {
425 String imgSrc;
426 if(node.getNodeName().toLowerCase().equals("img") &&
427 (imgSrc = ((JSObject) node).getMember("src").toString()) != null) {
428 pic = WebParser.getImageFromUrl(imgSrc, null, DisplayIO.getCurrentFrame(),
429 (float) FrameMouseActions.getX(), (float) FrameMouseActions.getY(), (int) width, null, null, null, null, null, 0, 0);
430 } else {
431 return;
432 }
433 }
434 pic.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
435 FrameMouseActions.pickup(pic);
436 } catch (Exception e1) {
437 // TODO Auto-generated catch block
438 e1.printStackTrace();
439 }
440 }
441 } else {
442 // Copy text and attach to cursor
443 Text t = new Text(selection);
444 t.setParent(DisplayIO.getCurrentFrame());
445 t.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
446 FrameMouseActions.pickup(t);
447 }
448 }
449 }
450 });
451
452 this._webEngine.load(url);
453 } catch (Exception e) {
454 e.printStackTrace();
455 }
456 }
457
458 public void navigate(String url) {
459 final String actualURL;
460 String urlLower = url.toLowerCase();
461 // check if protocol is missing
462 if (!(urlLower.startsWith("http://") || url.startsWith("https://") || urlLower.startsWith("ftp://") || urlLower.startsWith("file://"))) {
463 // check if it's a search
464 int firstSpace = url.indexOf(" ");
465 int firstDot = url.indexOf(".");
466 int firstSlash = url.indexOf('/');
467 int firstQuestion = url.indexOf('?');
468 int firstSQ;
469 if(firstSlash == -1) {
470 firstSQ = firstQuestion;
471 } else if(firstQuestion == -1) {
472 firstSQ = firstSlash;
473 } else {
474 firstSQ = -1;
475 }
476 if(firstDot <= 0 || // no '.' or starts with '.' -> search
477 (firstSpace != -1 && firstSpace < firstDot + 1) || // ' ' before '.' -> search
478 (firstSpace != -1 && firstSpace < firstSQ)) { // no '/' or '?' -> search
479 // make it a search
480 actualURL = NetworkSettings.SearchEngine.get() + url;
481 } else {
482 // add the missing protocol
483 actualURL = "http://" + url;
484 }
485 } else {
486 actualURL = url;
487 }
488 System.out.println(actualURL);
489 try {
490 Platform.runLater(new Runnable() {
491 @Override
492 public void run() {
493 try {
494 JfxBrowser.this._webEngine.load(actualURL);
495 } catch (Exception e) {
496 e.printStackTrace();
497 }
498 }
499 });
500 } catch (Exception e) {
501 e.printStackTrace();
502 }
503 }
504
505 /**
506 * Navigates JfxBrowser back through history. If end of history reached the user is notified via the MessageBay.
507 * Max size of history is 100 by default.
508 */
509 public void navigateBack() {
510 try {
511 Platform.runLater(new Runnable() {
512 @Override
513 public void run() {
514 try {
515 JfxBrowser.this._webEngine.getHistory().go(-1);
516 FreeItems.getInstance().clear();
517 } catch (IndexOutOfBoundsException e) {
518 MessageBay.displayMessage("Start of History");
519 }
520 }
521 });
522 } catch (Exception e) {
523 e.printStackTrace();
524 }
525 }
526
527 /**
528 * Navigates JfxBrowser forward through history. If end of history reached the user is notified via the MessageBay.
529 * Max size of history is 100 by default.
530 */
531 public void navigateForward() {
532 try {
533 Platform.runLater(new Runnable() {
534 @Override
535 public void run() {
536 try {
537 JfxBrowser.this._webEngine.getHistory().go(1);
538 FreeItems.getInstance().clear();
539 } catch (IndexOutOfBoundsException e) {
540 MessageBay.displayMessage("End of History");
541 }
542 }
543 });
544 } catch (Exception e) {
545 e.printStackTrace();
546 }
547 }
548
549 /**
550 * Refreshes webview by reloading the page.
551 */
552 public void refresh() {
553 try {
554 Platform.runLater(new Runnable() {
555 @Override
556 public void run() {
557 try {
558 JfxBrowser.this._webEngine.reload();
559 FreeItems.getInstance().clear();
560 MessageBay.displayMessage("Page Reloading");
561 } catch (Exception e) {
562 e.printStackTrace();
563 }
564 }
565 });
566 } catch (Exception e) {
567 e.printStackTrace();
568 }
569
570 }
571
572 /**
573 * Traverses DOM an turns elements into expeditee items.
574 */
575 public void getFrame() {
576 try {
577 WebParser.parsePage(this._webEngine, DisplayIO.getCurrentFrame());
578 } catch (Exception e) {
579 e.printStackTrace();
580 }
581 }
582
583 public void getFrameNew() {
584 // this.setSize(1000, 1000);
585 // this._browser.setBounds(getX(), getY(), getWidth(), getHeight());
586 // this.layout(this._browser);
587
588 try {
589 // hack to make sure we don't try parsing the page from within the JavaFX thread,
590 // because doing so causes deadlock
591 new Thread(new Runnable() {
592 public void run() {
593 WebParser.parsePageSimple(JfxBrowser.this._webEngine, JfxBrowser.this._webView, DisplayIO.getCurrentFrame());
594 }
595 }).start();
596 } catch (Exception e) {
597 e.printStackTrace();
598 }
599 }
600
601 /**
602 * Used to drop text items onto JfxBrowser widget. Does nothing if a text item is not attached to cursor. <br>
603 * "back" -> navigates back a page in browser's session history <br>
604 * "forward" -> navigates forward a page in browser's session history <br>
605 * "refresh" -> reloads current page <br>
606 * "getFrame" -> attempts to parse page into an expeditee frame <br>
607 * url -> all other text is assumed to be a url which browser attempts to navigate to
608 *
609 * @return Whether a JfxBrowser specific event is run.
610 *
611 */
612 @Override
613 public boolean ItemsLeftClickDropped() {
614 Text carried = null;
615 if ((carried = FreeItems.getTextAttachedToCursor()) == null) { // fails if no text is attached to cursor.
616 return false;
617 }
618
619 if(carried.getText().toLowerCase().equals(BACK)) {
620 navigateBack();
621 } else if(carried.getText().toLowerCase().equals(FORWARD)) {
622 navigateForward();
623 } else if(carried.getText().toLowerCase().equals(REFRESH)) {
624 refresh();
625 } else if(carried.getText().toLowerCase().equals(CONVERT)) {
626 getFrame();
627 } else {
628 String text = carried.getText().trim();
629 this.navigate(text);
630 FreeItems.getInstance().clear();
631 }
632
633 return true;
634 }
635
636 /**
637 * Used to enable expeditee like text-widget interaction for middle mouse clicks. Does nothing if a text item is not attached to cursor.
638 * @return false if a text-widget interaction did not occur, true if a text-widget interaction did occur.
639 */
640 @Override
641 public boolean ItemsMiddleClickDropped() {
642 if(ItemsRightClickDropped()) {
643 FreeItems.getInstance().clear(); // removed held text item - like normal expeditee middle click behaviour.
644 return true;
645 }
646 return false;
647 }
648
649 /**
650 * Used to enable expeditee like text-widget interaction for right mouse clicks. Does nothing if a text item is not attached to cursor.
651 * @return false if a text-widget interaction did not occur, true if a text-widget interaction did occur.
652 */
653 @Override
654 public boolean ItemsRightClickDropped() {
655 Text t = null;
656 if((t = FreeItems.getTextAttachedToCursor()) == null) { // fails if no text item is attached to the cursor.
657 return false;
658 }
659
660 final int x = FrameMouseActions.getX() - this.getX(), y = FrameMouseActions.getY() - this.getY();
661 if(!this._urlField.getBoundsInParent().contains(x, y)) {
662 // fails if not clicking on urlField
663 return false;
664 }
665
666 final String insert = t.getText();
667 Platform.runLater(new Runnable() {
668 @Override
669 public void run() {
670 // Inserts text in text item into urlField at the position of the mouse.
671 String s = JfxBrowser.this._urlField.getText();
672 int index = getCaretFromCoord(JfxBrowser.this._urlField, getMouseEventForPosition(JfxBrowser.this._backupEvent, JfxBrowser.this._urlField, x, y));
673 if(index < s.length()) {
674 s = s.substring(0, index) + insert + s.substring(index);
675 } else {
676 s = s + insert;
677 }
678 JfxBrowser.this._urlField.setText(s);
679 }
680 });
681
682 return true;
683 }
684
685 @Override
686 protected String[] getArgs() {
687 String[] r = null;
688 if (this._webView != null) {
689 try {
690 r = new String[] { this._webEngine.getLocation() };
691 } catch (Exception e) {
692 e.printStackTrace();
693 }
694 }
695 return r;
696 }
697}
Note: See TracBrowser for help on using the repository browser.