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

Last change on this file since 829 was 829, checked in by ngw8, 10 years ago

More updates to jfxbrowser appearance - added progress bar behind URL bar, + minor CSS changes. Made go button actually work.

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