Changeset 801


Ignore:
Timestamp:
01/31/14 16:42:05 (10 years ago)
Author:
jts21
Message:

Make JfxBrowser use only JavaFX Nodes, and make WebParser get images with webView.snapshot() instead of blitting the parent Swing component onto an Image

Location:
trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/expeditee/io/WebParser.java

    r796 r801  
    1111import java.net.MalformedURLException;
    1212import java.net.URL;
     13import java.nio.IntBuffer;
    1314import java.text.SimpleDateFormat;
    1415
     
    1819import javafx.beans.value.ObservableValue;
    1920import javafx.concurrent.Worker.State;
     21import javafx.embed.swing.SwingFXUtils;
     22import javafx.scene.SnapshotParameters;
     23import javafx.scene.image.WritableImage;
     24import javafx.scene.image.WritablePixelFormat;
    2025import javafx.scene.web.WebEngine;
     26import javafx.scene.web.WebView;
    2127
    2228import javax.imageio.ImageIO;
     
    3743import org.w3c.dom.Node;
    3844import org.w3c.dom.html.HTMLBodyElement;
     45
     46
     47
     48
     49
     50
    3951
    4052/*
     
    279291         *            The Expeditee frame to output the converted page to
    280292         */
    281         public static void parsePageSimple(final WebEngine webEngine, final Object webView, final JComponent jfxPanel, final Frame frame) {
     293        public static void parsePageSimple(final WebEngine webEngine, final WebView webView, final Frame frame) {
    282294                try {
    283295                        final Object notifier = new Object();
     
    354366                                                System.out.println("hidden");
    355367
    356                                                 BufferedImage image = new BufferedImage(jfxPanel.getWidth(), jfxPanel.getHeight(), BufferedImage.TYPE_INT_ARGB);
    357 
    358                                                 Graphics graphics = image.createGraphics();
     368                                                WritableImage tmp = new WritableImage((int)webView.getWidth(), (int)webView.getHeight());
     369
    359370                                                System.out.println("painted");
    360371                                                // Drawing the JfxPanel (containing the webview) to the image
    361                                                 jfxPanel.paint(graphics);
     372                                                webView.snapshot(new SnapshotParameters(), tmp);
     373                                               
     374                                                // Getting a BufferedImage from the JavaFX image
     375                                                BufferedImage image = SwingFXUtils.fromFXImage(tmp, null);
    362376
    363377                                                try {
     
    425439                                                }
    426440
    427                                                 graphics.dispose();
    428441                                                image.flush();
    429442
  • trunk/src/org/expeditee/items/widgets/JfxBrowser.java

    r767 r801  
    11package org.expeditee.items.widgets;
    2 
    3 import java.awt.BorderLayout;
    4 import java.awt.Color;
    5 import java.awt.Component;
    6 import java.awt.Font;
    7 import java.awt.Point;
    8 import java.awt.event.ActionEvent;
    9 import java.awt.event.ActionListener;
    10 import java.awt.event.ComponentEvent;
    11 import java.awt.event.ComponentListener;
    12 import java.awt.event.FocusEvent;
    13 import java.awt.event.FocusListener;
    14 import java.awt.event.KeyEvent;
    15 import java.awt.event.KeyListener;
    16 import java.awt.event.MouseEvent;
    17 import java.awt.event.MouseListener;
    18 import java.awt.event.MouseMotionListener;
    192
    203/*
     
    269 * If this fails, 'ant build-nojfx' will build with the JfxBrowser, WebParser and JfxbrowserActions excluded from the build path.
    2710 */
     11import java.awt.Point;
    2812
    2913import javafx.application.Platform;
     
    3216import javafx.concurrent.Worker.State;
    3317import javafx.embed.swing.JFXPanel;
     18import javafx.event.ActionEvent;
     19import javafx.event.Event;
     20import javafx.event.EventDispatchChain;
     21import javafx.event.EventDispatcher;
    3422import javafx.event.EventHandler;
     23import javafx.geometry.Point2D;
     24import javafx.geometry.Rectangle2D;
    3525import javafx.scene.Scene;
     26import javafx.scene.control.Button;
     27import javafx.scene.control.TextField;
     28import javafx.scene.input.KeyEvent;
     29import javafx.scene.input.MouseButton;
     30import javafx.scene.input.MouseEvent;
     31import javafx.scene.layout.HBox;
     32import javafx.scene.layout.Priority;
     33import javafx.scene.layout.VBox;
    3634import javafx.scene.web.WebEngine;
    3735import javafx.scene.web.WebView;
    3836
    39 import javax.swing.JButton;
    4037import javax.swing.JComponent;
    41 import javax.swing.JLabel;
    42 import javax.swing.JPanel;
    43 import javax.swing.JTextField;
    44 import javax.swing.JToolBar;
    45 import javax.swing.SwingConstants;
    46 import javax.swing.text.BadLocationException;
    4738
    4839import org.expeditee.gui.DisplayIO;
     
    5546import org.expeditee.settings.network.NetworkSettings;
    5647
     48import com.sun.javafx.scene.control.skin.TextFieldSkin;
     49import com.sun.javafx.scene.text.HitInfo;
     50
    5751/**
    5852 * Web browser using a JavaFX WebView.
     
    7266        public static final int HORZ_CROP = 16;
    7367       
    74         private WebBrowserPanel _browser;
     68        private JFXPanel _panel;
     69        private WebView _webView;
     70        private WebEngine _webEngine;
     71        private TextField _urlField;
     72       
     73        private MouseButton _buttonDownId = MouseButton.NONE;
    7574
    7675        static {
    7776                Platform.setImplicitExit(false);
    7877        }
    79 
    80         private static class WebBrowserPanel extends JPanel implements ComponentListener {
    81 
    82                 private static final long serialVersionUID = 1L;
    83 
    84                 WebView webview;
    85                 WebEngine webEngine;
    86                 JFXPanel jfxPanel;
    87                 JfxBrowser owner;
    88 
    89                 /**
    90                  * ID of the mouse button that is currently pressed.
    91                  * <p>
    92                  * Uses {@link MouseEvent} constants
    93                  */
    94                 private int buttonDownId;
    95 
    96                 private JTextField urlField;
    97 
    98                 /**
    99                  * @return A JPanel that either contains a JavaFX Webview or an empty panel if the JFX panel can't be initialized
    100                  */
    101                 public WebBrowserPanel(final String url) {
    102 
    103                         super(new BorderLayout());
    104                         this.addComponentListener(this);
    105                         try {
    106                                 jfxPanel = new JFXPanel();
    107 
    108                                 // Toolbar (that can't be dragged) to hold the nav buttons, url bar, etc
    109                                 JToolBar toolBar = new JToolBar();
    110                                 toolBar.setFloatable(false);
    111 
    112                                 JButton backButton = new JButton("Back");
    113                                 toolBar.add(backButton);
    114 
    115                                 JButton forwardButton = new JButton("Forward");
    116                                 toolBar.add(forwardButton);
    117 
    118                                 urlField = new JTextField(url);
    119                                 toolBar.add(urlField);
    120 
    121                                 JButton convertButton = new JButton("Convert");
    122                                 toolBar.add(convertButton);
    123 
    124                                 JButton convertButtonNew = new JButton("Convert (New Method)");
    125                                 toolBar.add(convertButtonNew);
    126 
    127                                 backButton.addActionListener(new ActionListener() {
    128                                         @Override
    129                                         public void actionPerformed(ActionEvent arg0) {
    130                                                 owner.navigateBack();
    131                                         }
    132                                 });
    133 
    134                                 forwardButton.addActionListener(new ActionListener() {
    135                                         @Override
    136                                         public void actionPerformed(ActionEvent arg0) {
    137                                                 owner.navigateForward();
    138                                         }
    139                                 });
    140                                
    141                                 convertButton.addActionListener(new ActionListener() {
    142                                         @Override
    143                                         public void actionPerformed(ActionEvent arg0) {
    144                                                 owner.getFrame();
    145                                         }
    146                                 });
    147 
    148                                 convertButtonNew.addActionListener(new ActionListener() {
    149                                         @Override
    150                                         public void actionPerformed(ActionEvent arg0) {
    151                                                 owner.getFrameNew();
    152                                         }
    153                                 });
    154 
    155                                 urlField.addActionListener(new ActionListener() {
    156                                         @Override
    157                                         public void actionPerformed(ActionEvent e) {
    158                                                 owner.navigate(e.getActionCommand());
    159                                         }
    160                                 });
    161 
    162                                 urlField.addKeyListener(new KeyListener() {
    163 
    164                                         @Override
    165                                         public void keyTyped(KeyEvent arg0) {
    166                                                 // Hiding the cursor when typing, to be more Expeditee-like
    167                                                 DisplayIO.setCursor(org.expeditee.items.Item.HIDDEN_CURSOR);
    168                                         }
    169 
    170                                         @Override
    171                                         public void keyReleased(KeyEvent arg0) { // TODO: remove if not used
    172                                         }
    173 
    174                                         @Override
    175                                         public void keyPressed(KeyEvent arg0) { // TODO: remove if not used
    176                                         }
    177                                 });
    178 
    179                                 urlField.addMouseMotionListener(new MouseMotionListener() {
    180 
    181                                         @Override
    182                                         public void mouseMoved(MouseEvent arg0) {
    183                                                 // Checking if the user has been typing - if so, move the cursor to the caret position
    184                                                 if (DisplayIO.getCursor() == Item.HIDDEN_CURSOR) {
    185                                                         DisplayIO.setCursor(org.expeditee.items.Item.TEXT_CURSOR);
    186                                                         try {
    187                                                                 DisplayIO.setCursorPosition(
    188                                                                                 // Expeditee gives coords relative to the window, Swing gives it relative to the
    189                                                                                 // screen
    190                                                                                 urlField.getLocationOnScreen().x + urlField.modelToView(urlField.getCaretPosition() + 1).x - org.expeditee.gui.Browser._theBrowser.getOrigin().x,
    191                                                                                 urlField.getLocationOnScreen().y + urlField.modelToView(urlField.getCaretPosition()).y - org.expeditee.gui.Browser._theBrowser.getOrigin().y);
    192 
    193                                                         } catch (BadLocationException e) {}
    194                                                 } else {
    195                                                         // Otherwise, move the caret to the cursor location
    196                                                         urlField.setCaretPosition(urlField.viewToModel(arg0.getPoint()));
    197                                                 }
    198                                         }
    199 
    200                                         @Override
    201                                         public void mouseDragged(MouseEvent arg0) {
    202                                                 // Selecting text when the mouse is dragged with the middle or right button pressed. If-else
    203                                                 // determines which direction the user is selecting in
    204                                                 if (buttonDownId == MouseEvent.BUTTON2 || buttonDownId == MouseEvent.BUTTON3) {
    205                                                         if (urlField.viewToModel(arg0.getPoint()) < urlField.getSelectionEnd()) {
    206                                                                 urlField.select(urlField.viewToModel(arg0.getPoint()), urlField.getSelectionEnd());
    207                                                         } else {
    208                                                                 urlField.select(urlField.getSelectionStart(), urlField.viewToModel(arg0.getPoint()));
    209                                                         }
    210                                                 }
    211                                         }
    212                                 });
    213                                
    214                                 urlField.addFocusListener(new FocusListener() {
     78       
     79        private static Point getCoordFromCaret(TextField text) {
     80                TextFieldSkin skin = (TextFieldSkin) text.getSkin();
     81               
     82                Point2D onScreen = text.localToScreen(0, 0);
     83                double x = onScreen.getX() - org.expeditee.gui.Browser._theBrowser.getOrigin().x;
     84                double y = onScreen.getY() - org.expeditee.gui.Browser._theBrowser.getOrigin().y;
     85               
     86                Rectangle2D cp = skin.getCharacterBounds(text.getCaretPosition());
     87               
     88                return new Point((int) (cp.getMinX() + x), (int) (cp.getMinY() + y));
     89        }
     90       
     91        private static int getCaretFromCoord(TextField text, int x, int y) {
     92                TextFieldSkin skin = (TextFieldSkin) text.getSkin();
     93               
     94                MouseEvent fakeMouseEvent = new MouseEvent(
     95                        MouseEvent.MOUSE_MOVED, //EventType<? extends MouseEvent> eventType
     96                        x - text.getBoundsInParent().getMinX(), // x
     97                        y - text.getBoundsInParent().getMinY(), // y
     98            FrameMouseActions.getX() + org.expeditee.gui.Browser._theBrowser.getOrigin().x, // screen x
     99            FrameMouseActions.getY() + org.expeditee.gui.Browser._theBrowser.getOrigin().y, // screen y
     100            MouseButton.NONE, // button
     101            0,     // click count
     102            false, // shift down
     103            false, // control down
     104            false, // alt down
     105            false, // meta down
     106            false, // primary button down
     107            false, // middle button down
     108            false, // secondary button down
     109            true,  // synthesized
     110            false, // popup trigger
     111            false, // still since press
     112            null   // pick result
     113        );
     114               
     115                HitInfo hit = skin.getIndex(fakeMouseEvent);
     116               
     117                return hit.getInsertionIndex();
     118        }
     119
     120        public JfxBrowser(Text source, final String[] args) {
     121                // Initial page is either the page stored in the arguments (if there is one stored) or the homepage
     122                super(source, new JFXPanel(), -1, 500, -1, -1, 300, -1);
     123
     124                _panel = (JFXPanel) _swingComponent;
     125               
     126                Platform.runLater(new Runnable() {
     127                        @Override
     128                        public void run() {
     129                                initFx((args != null && args.length > 0) ? args[0] : NetworkSettings.HomePage.get());
     130                        }
     131                });
     132        }
     133       
     134        /**
     135         * Sets up the browser frame. JFX requires this to be run on a new thread.
     136         *
     137         * @param url
     138         *            The URL to be loaded when the browser is created
     139         */
     140        private void initFx(String url) {
     141                try {
     142                        VBox vertical = new VBox();
     143                        HBox horizontal = new HBox();
     144                       
     145                        Button backButton = new Button("Back");
     146                        backButton.setMinWidth(Button.USE_PREF_SIZE);
     147                        Button forwardButton = new Button("Forward");
     148                        forwardButton.setMinWidth(Button.USE_PREF_SIZE);
     149                        this._urlField = new TextField(url);
     150                        this._urlField.setMinWidth(0);
     151                        this._urlField.setMaxWidth(Double.MAX_VALUE);
     152                        Button convertButton = new Button("Convert");
     153                        convertButton.setMinWidth(Button.USE_PREF_SIZE);
     154                        Button convertButtonNew = new Button("Convert (New Method)");
     155                        convertButtonNew.setMinWidth(Button.USE_PREF_SIZE);
     156                       
     157                        horizontal.getChildren().addAll(backButton, forwardButton, this._urlField, convertButton, convertButtonNew);
     158                       
     159                        HBox.setHgrow(backButton, Priority.NEVER);
     160                        HBox.setHgrow(forwardButton, Priority.NEVER);
     161                        HBox.setHgrow(convertButton, Priority.NEVER);
     162                        HBox.setHgrow(convertButtonNew, Priority.NEVER);
     163                        HBox.setHgrow(this._urlField, Priority.ALWAYS);
     164                       
     165                        this._webView = new WebView();
     166                        this._webEngine = this._webView.getEngine();
     167                       
     168                        vertical.getChildren().addAll(horizontal, this._webView);
     169                       
     170                        Scene scene = new Scene(vertical);
     171
     172                        this._panel.setScene(scene);
     173                       
     174                        // Disable right click menu
     175                        this._webView.setContextMenuEnabled(false);
     176                        final EventDispatcher initial = this._urlField.getEventDispatcher();
     177                        this._urlField.setEventDispatcher(new EventDispatcher() {
     178                                @Override
     179                                public Event dispatchEvent(Event e, EventDispatchChain tail) {
     180                                        if (e instanceof MouseEvent) {
     181                                                MouseEvent m = (MouseEvent) e;
     182                        if (m.getButton() == MouseButton.SECONDARY && m.getEventType() == MouseEvent.MOUSE_RELEASED) {
     183                            e.consume();
     184                            JfxBrowser.this._urlField.getOnMouseReleased().handle(m);
     185                        }
     186                    }
     187                    return initial.dispatchEvent(e, tail);
     188                                }
     189                        });
     190                       
     191                        backButton.setOnAction(new EventHandler<ActionEvent>() {
     192                                @Override
     193                public void handle(ActionEvent e) {
     194                    navigateBack();
     195                }
     196                        });
     197
     198                        forwardButton.setOnAction(new EventHandler<ActionEvent>() {
     199                                @Override
     200                public void handle(ActionEvent e) {
     201                    navigateForward();
     202                }
     203                        });
     204                       
     205                       
     206                        convertButton.setOnAction(new EventHandler<ActionEvent>() {
     207                                @Override
     208                public void handle(ActionEvent e) {
     209                    getFrame();
     210                }
     211                        });
     212
     213                        convertButtonNew.setOnAction(new EventHandler<ActionEvent>() {
     214                                @Override
     215                public void handle(ActionEvent e) {
     216                    getFrameNew();
     217                }
     218                        });
     219
     220                        this._urlField.setOnAction(new EventHandler<ActionEvent>() {
     221                                @Override
     222                public void handle(ActionEvent e) {
     223                    navigate(JfxBrowser.this._urlField.getText());
     224                }
     225                        });
     226
     227                        this._urlField.setOnKeyTyped(new EventHandler<KeyEvent>() {
     228                                @Override
     229                                public void handle(KeyEvent e) {
     230                                        // Hiding the cursor when typing, to be more Expeditee-like
     231                                        DisplayIO.setCursor(org.expeditee.items.Item.HIDDEN_CURSOR);
     232                                }
     233                        });
     234
     235                        this._urlField.setOnMouseMoved(new EventHandler<MouseEvent>() {
     236                                @Override
     237                                public void handle(MouseEvent e) {
     238                                        // Checking if the user has been typing - if so, move the cursor to the caret position
     239                                        if (DisplayIO.getCursor() == Item.HIDDEN_CURSOR) {
     240                                                DisplayIO.setCursor(org.expeditee.items.Item.TEXT_CURSOR);
     241                                                DisplayIO.setCursorPosition(getCoordFromCaret(JfxBrowser.this._urlField));
     242                                        } else {
     243                                                // Otherwise, move the caret to the cursor location
     244                                                int x = FrameMouseActions.getX() - JfxBrowser.this.getX(), y = FrameMouseActions.getY() - JfxBrowser.this.getY();
     245                                                JfxBrowser.this._urlField.positionCaret(getCaretFromCoord(JfxBrowser.this._urlField, x, y));
     246                                        }
     247                                }
     248                        });
     249                       
     250                        this._urlField.setOnMouseDragged(new EventHandler<MouseEvent>() {
     251                                @Override
     252                                public void handle(MouseEvent e) {
     253                                        TextFieldSkin skin = (TextFieldSkin) JfxBrowser.this._urlField.getSkin();
    215254                                       
    216                                         @Override
    217                                         public void focusGained(FocusEvent arg0) {
     255                                        if (!JfxBrowser.this._urlField.isDisabled()) {
     256                        if (JfxBrowser.this._buttonDownId == MouseButton.MIDDLE || JfxBrowser.this._buttonDownId == MouseButton.SECONDARY) {
     257                            if (!(e.isControlDown() || e.isAltDown() || e.isShiftDown() || e.isMetaDown())) {
     258                                skin.positionCaret(skin.getIndex(e), true);
     259                            }
     260                        }
     261                    }
     262                                }
     263                        });
     264                       
     265                        this._urlField.focusedProperty().addListener(new ChangeListener<Boolean>() {
     266                                @Override
     267                public void changed(ObservableValue<? extends Boolean> property, Boolean oldValue, Boolean newValue) {
     268                                        if(newValue.booleanValue()) {
    218269                                                DisplayIO.setCursor(org.expeditee.items.Item.TEXT_CURSOR);
    219                                         }
    220 
    221                                         @Override
    222                                         public void focusLost(FocusEvent arg0) {
     270                                        } else {
    223271                                                // Restoring the standard cursor, since it is changed to a text cursor when focus is gained
    224272                                                DisplayIO.setCursor(org.expeditee.items.Item.DEFAULT_CURSOR);
    225273                                        }
    226                                 });
    227 
    228                                 urlField.addMouseListener(new MouseListener() {
    229 
    230                                         @Override
    231                                         public void mouseReleased(MouseEvent arg0) {
    232                                                 buttonDownId = MouseEvent.NOBUTTON;
    233 
    234                                                 Text item;
    235 
    236                                                 // If nothing is selected, then select all the text so that it will be copied/moved
    237                                                 if (urlField.getSelectedText() == null) {
    238                                                         urlField.selectAll();
     274                }
     275                        });
     276
     277                        this._urlField.setOnMouseReleased(new EventHandler<MouseEvent>() {
     278                                @Override
     279                public void handle(MouseEvent e) {
     280                    JfxBrowser.this._buttonDownId = MouseButton.NONE;
     281
     282                                        Text item;
     283
     284                                        // If nothing is selected, then select all the text so that it will be copied/moved
     285                                        if (JfxBrowser.this._urlField.getSelectedText() == null || JfxBrowser.this._urlField.getSelectedText().length() == 0) {
     286                                                JfxBrowser.this._urlField.selectAll();
     287                                        }
     288
     289                                        if (e.getButton() == MouseButton.SECONDARY) {
     290                                                // Right mouse button released, so copy the selection (i.e. don't remove the original)
     291                                                item = DisplayIO.getCurrentFrame().createNewText(JfxBrowser.this._urlField.getSelectedText());
     292                                                FrameMouseActions.pickup(item);
     293                                        } else if (e.getButton() == MouseButton.MIDDLE) {
     294                                                // Middle mouse button released, so copy the selection then remove it from the URL field
     295                                                item = DisplayIO.getCurrentFrame().createNewText(JfxBrowser.this._urlField.getSelectedText());
     296                                                JfxBrowser.this._urlField.setText(
     297                                                                JfxBrowser.this._urlField.getText().substring(0, JfxBrowser.this._urlField.getSelection().getStart())
     298                                                                + JfxBrowser.this._urlField.getText().substring(JfxBrowser.this._urlField.getSelection().getEnd(),
     299                                                                                JfxBrowser.this._urlField.getText().length()));
     300
     301                                                FrameMouseActions.pickup(item);
     302                                        }
     303                }
     304                        });
     305                       
     306                        this._urlField.setOnMousePressed(new EventHandler<MouseEvent>() {
     307                                @Override
     308                public void handle(MouseEvent e) {
     309                                        JfxBrowser.this._buttonDownId = e.getButton();
     310                                }
     311                        });
     312
     313                        this._webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
     314
     315                                @Override
     316                                public void changed(ObservableValue<? extends State> ov, State oldState, State newState) {
     317
     318                                        switch (newState) {
     319                                        case READY: // READY
     320                                                // MessageBay.displayMessage("WebEngine ready");
     321                                                break;
     322                                        case SCHEDULED: // SCHEDULED
     323                                                // MessageBay.displayMessage("Scheduled page load");
     324                                                break;
     325                                        case RUNNING: // RUNNING
     326                                                System.out.println("Loading page!");
     327
     328                                                // Updating the URL bar to display the URL of the page being loaded
     329                                                JfxBrowser.this._urlField.setText(JfxBrowser.this._webEngine.getLocation());
     330
     331                                                break;
     332                                        case SUCCEEDED: // SUCCEEDED
     333                                                MessageBay.displayMessage("Finished loading page");
     334                                                break;
     335                                        case CANCELLED: // CANCELLED
     336                                                MessageBay.displayMessage("Cancelled loading page");
     337                                                break;
     338                                        case FAILED: // FAILED
     339                                                MessageBay.displayMessage("Failed to load page");
     340                                                break;
     341                                        }
     342                                }
     343                        });
     344                       
     345                        // Captures mouse click events on webview to enable expeditee like behavior for JavaFX browser.
     346                        this._webView.setOnMouseClicked(new EventHandler<javafx.scene.input.MouseEvent>() {
     347                                @Override
     348                                public void handle(javafx.scene.input.MouseEvent e) {
     349                                        switch (e.getButton()) {
     350                                        case SECONDARY:
     351                                                // Gets text currently selected in webview
     352                                                String selection = (String) JfxBrowser.this._webEngine.executeScript("window.getSelection().toString()");
     353
     354                                                // Do nothing if no text is selected
     355                                                if (!selection.equals("")) {
     356                                                        // Copy text and attach to cursor
     357                                                        Text t = new Text(selection);
     358                                                        t.setParent(DisplayIO.getCurrentFrame());
     359                                                        t.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
     360                                                        FrameMouseActions.pickup(t);
    239361                                                }
    240362
    241                                                 if (arg0.getButton() == MouseEvent.BUTTON3) {
    242                                                         // Right mouse button released, so copy the selection (i.e. don't remove the original)
    243                                                         item = DisplayIO.getCurrentFrame().createNewText(urlField.getSelectedText());
    244                                                         FrameMouseActions.pickup(item);
    245                                                 } else if (arg0.getButton() == MouseEvent.BUTTON2) {
    246                                                         // Middle mouse button released, so copy the selection then remove it from the URL field
    247                                                         item = DisplayIO.getCurrentFrame().createNewText(urlField.getSelectedText());
    248                                                         urlField.setText(urlField.getText().substring(0, urlField.getSelectionStart()) + urlField.getText().substring(urlField.getSelectionEnd(), urlField.getText().length()));
    249 
    250                                                         FrameMouseActions.pickup(item);
    251                                                 }
    252                                         }
    253 
    254                                         @Override
    255                                         public void mousePressed(MouseEvent arg0) {
    256                                                 buttonDownId = arg0.getButton();
    257                                                
    258                                         }
    259 
    260                                         @Override
    261                                         public void mouseExited(MouseEvent arg0) {
    262                                         }
    263 
    264                                         @Override
    265                                         public void mouseEntered(MouseEvent arg0) {
    266                                         }
    267 
    268                                         @Override
    269                                         public void mouseClicked(MouseEvent arg0) {
    270                                         }
    271                                 });
    272 
    273                                 add(toolBar, BorderLayout.PAGE_START);
    274 
    275                                 this.add((Component) jfxPanel);
    276 
    277                                 Platform.runLater(new Runnable() {
    278                                         @Override
    279                                         public void run() {
    280                                                 initFx(url);
    281                                         }
    282                                 });
    283                         } catch (Exception e) {
    284                                 e.printStackTrace();
    285                                 // if this occurs JavaFX was probably missing
    286                                 this.removeAll();
    287                                 JLabel label = new JLabel("<html><p style=\"text-align: center;\">Failed to load<br/>Most likely JavaFX could not be found<br/>Make sure you are running at least Java 7<br/>(Preferably Java 8)</p></html>");
    288                                 label.setHorizontalAlignment(SwingConstants.CENTER);
    289                                 label.setForeground(Color.RED);
    290                                 label.setFont(new Font("sans-serif", 0, 20));
    291                                 this.add(label);
    292                         }
    293                        
    294                         // Setting bg color to be the same as bg color of widgets when they're being dragged/resized
    295                         this.setBackground(new Color(100, 100, 100));
    296                 }
    297 
    298                 /**
    299                  * Sets up the browser frame. JFX requires this to be run on a new thread.
    300                  *
    301                  * @param url
    302                  *            The URL to be loaded when the browser is created
    303                  */
    304                 private void initFx(String url) {
    305                         try {
    306                                 this.webview = new WebView();
    307 
    308                                 this.webEngine = this.webview.getEngine();
    309 
    310                                 Scene scene = new Scene(this.webview);
    311 
    312                                 this.jfxPanel.setScene(scene);
    313 
    314                                 this.webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
    315 
    316                                         @Override
    317                                         public void changed(ObservableValue<? extends State> ov, State oldState, State newState) {
    318 
    319                                                 switch (newState) {
    320                                                 case READY: // READY
    321                                                         // MessageBay.displayMessage("WebEngine ready");
    322                                                         break;
    323                                                 case SCHEDULED: // SCHEDULED
    324                                                         // MessageBay.displayMessage("Scheduled page load");
    325                                                         break;
    326                                                 case RUNNING: // RUNNING
    327                                                         System.out.println("Loading page!");
    328 
    329                                                         // Updating the URL bar to display the URL of the page being loaded
    330                                                         WebBrowserPanel.this.urlField.setText(WebBrowserPanel.this.webEngine.getLocation());
    331 
    332                                                         break;
    333                                                 case SUCCEEDED: // SUCCEEDED
    334                                                         MessageBay.displayMessage("Finished loading page");
    335                                                         break;
    336                                                 case CANCELLED: // CANCELLED
    337                                                         MessageBay.displayMessage("Cancelled loading page");
    338                                                         break;
    339                                                 case FAILED: // FAILED
    340                                                         MessageBay.displayMessage("Failed to load page");
    341                                                         break;
    342                                                 }
    343                                         }
    344                                 });
    345                                
    346                                 // Captures mouse click events on webview to enable expeditee like behavior for JavaFX browser.
    347                                 this.webview.setOnMouseClicked(new EventHandler<javafx.scene.input.MouseEvent>() {
    348                                         @Override
    349                                         public void handle(javafx.scene.input.MouseEvent e) {
    350                                                 switch (e.getButton()) {
    351                                                 case SECONDARY:
    352                                                         // Gets text currently selected in webview
    353                                                         String selection = (String) webEngine.executeScript("window.getSelection().toString()");
    354 
    355                                                         // Do nothing if no text is selected
    356                                                         if (!selection.equals("")) {
    357                                                                 // Copy text and attach to cursor
    358                                                                 Text t = new Text(selection);
    359                                                                 t.setParent(DisplayIO.getCurrentFrame());
    360                                                                 t.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
    361                                                                 FrameMouseActions.pickup(t);
    362                                                         }
    363 
    364                                                         break;
    365                                                 }
    366                                         }
    367                                 });
    368 
    369                                 // Disables JavaFX webview's right click menu
    370                                 this.webview.setContextMenuEnabled(false);
    371 
    372                                 this.webEngine.load(url);
    373                         } catch (Exception e) {
    374                                 e.printStackTrace();
    375                         }
    376                 }
    377 
    378                 @Override
    379                 public void componentHidden(ComponentEvent e) {
    380                 }
    381 
    382                 @Override
    383                 public void componentMoved(ComponentEvent e) {
    384                 }
    385 
    386                 @Override
    387                 public void componentResized(ComponentEvent e) {
    388                         // BorderLayout on the JPanel removes the need for explicitly resizing anything here
    389                 }
    390 
    391                 @Override
    392                 public void componentShown(ComponentEvent e) {
    393                 }
    394         }
    395 
    396         public JfxBrowser(Text source, String[] args) {
    397                 // Initial page is either the page stored in the arguments (if there is one stored) or the homepage
    398                 super(source, new WebBrowserPanel((args != null && args.length > 0) ? args[0] : NetworkSettings.HomePage.get()), -1, 500, -1, -1, 300, -1);
    399 
    400                 _browser = (WebBrowserPanel) _swingComponent;
    401                 _browser.owner = this;
     363                                                break;
     364                                        }
     365                                }
     366                        });
     367
     368                        this._webEngine.load(url);
     369                } catch (Exception e) {
     370                        e.printStackTrace();
     371                }
    402372        }
    403373
     
    438408                                public void run() {
    439409                                        try {
    440                                                 JfxBrowser.this._browser.webEngine.load(actualURL);
     410                                                JfxBrowser.this._webEngine.load(actualURL);
    441411                                        } catch (Exception e) {
    442412                                                e.printStackTrace();
     
    459429                        public void run() {
    460430                                try {
    461                                         JfxBrowser.this._browser.webEngine.getHistory().go(-1);
     431                                        JfxBrowser.this._webEngine.getHistory().go(-1);
    462432                                        FreeItems.getInstance().clear();
    463433                                } catch (IndexOutOfBoundsException e) {
     
    481451                        public void run() {
    482452                                try {
    483                                         JfxBrowser.this._browser.webEngine.getHistory().go(1);
     453                                        JfxBrowser.this._webEngine.getHistory().go(1);
    484454                                        FreeItems.getInstance().clear();
    485455                                } catch (IndexOutOfBoundsException e) {
     
    502472                        public void run() {
    503473                                try {
    504                                         JfxBrowser.this._browser.webEngine.reload();
     474                                        JfxBrowser.this._webEngine.reload();
    505475                                        FreeItems.getInstance().clear();
    506476                                        MessageBay.displayMessage("Page Reloading");
     
    521491        public void getFrame() {
    522492                try {
    523                         WebParser.parsePage(this._browser.webEngine, DisplayIO.getCurrentFrame());
     493                        WebParser.parsePage(this._webEngine, DisplayIO.getCurrentFrame());
    524494                } catch (Exception e) {
    525495                        e.printStackTrace();
     
    533503
    534504                try {
    535                         WebParser.parsePageSimple(JfxBrowser.this._browser.webEngine, JfxBrowser.this._browser.webview, (JComponent) JfxBrowser.this._browser.jfxPanel, DisplayIO.getCurrentFrame());
     505                        // hack to make sure we don't try parsing the page from within the JavaFX thread,
     506                        // because doing so causes deadlock
     507                        new Thread(new Runnable() {
     508                                public void run() {
     509                                        WebParser.parsePageSimple(JfxBrowser.this._webEngine, JfxBrowser.this._webView, DisplayIO.getCurrentFrame());
     510                                }
     511                        }).start();
    536512                } catch (Exception e) {
    537513                        e.printStackTrace();
     
    580556        @Override
    581557        public boolean ItemsMiddleClickDropped() {
    582                 Text t = null;
    583                 if((t = FreeItems.getTextAttachedToCursor()) == null) { // fails if no text item is attached to the cursor.
    584                         return false;
    585                 }
    586 
    587                 Point p = new Point(FrameMouseActions.getX() - this.getX(), FrameMouseActions.getY() - this.getY());
    588 
    589                 if(!_browser.urlField.contains(p)) {                                    // fails if not clicking on urlField
    590                         return false;
    591                 }
    592 
    593                 // Inserts text in text item into urlField at the position of the mouse.
    594                 String s = _browser.urlField.getText();
    595                 int index = _browser.urlField.viewToModel(new Point(p.x - _browser.urlField.getX(), p.y - _browser.urlField.getY()));
    596                 s = s.substring(0, index) + t.getText() + s.substring(index);
    597                 _browser.urlField.setText(s);
    598 
    599                 FreeItems.getInstance().clear();                                                // removed held text item - like normal expeditee middle click behaviour.
    600 
    601                 return true;
     558                if(ItemsRightClickDropped()) {
     559                        FreeItems.getInstance().clear();                                                // removed held text item - like normal expeditee middle click behaviour.
     560                        return true;
     561                }
     562                return false;
    602563        }
    603564       
     
    613574                }
    614575
    615                 Point p = new Point(FrameMouseActions.getX() - this.getX(), FrameMouseActions.getY() - this.getY());
    616 
    617                 if(!_browser.urlField.contains(p)) {                                    // fails if not clicking on urlField
     576                final int x = FrameMouseActions.getX() - this.getX(), y = FrameMouseActions.getY() - this.getY();
     577                if(!this._urlField.getBoundsInParent().contains(x, y)) {
     578                        // fails if not clicking on urlField
    618579                        return false;
    619580                }
    620581
    621                 // Inserts text in text item into urlField at the position of the mouse.
    622                 String s = _browser.urlField.getText();
    623                 int index = _browser.urlField.viewToModel(new Point(p.x - _browser.urlField.getX(), p.y - _browser.urlField.getY()));
    624                 s = s.substring(0, index) + t.getText() + s.substring(index);
    625                 _browser.urlField.setText(s);
     582                final String insert = t.getText();
     583                Platform.runLater(new Runnable() {
     584                        @Override
     585                        public void run() {
     586                                // Inserts text in text item into urlField at the position of the mouse.
     587                        String s = JfxBrowser.this._urlField.getText();
     588                        int index = getCaretFromCoord(JfxBrowser.this._urlField, x, y);
     589                        if(index < s.length()) {
     590                                s = s.substring(0, index) + insert + s.substring(index);
     591                        } else {
     592                                s = s + insert;
     593                        }
     594                        JfxBrowser.this._urlField.setText(s);
     595                        }
     596                });
    626597
    627598                return true;
     
    631602        protected String[] getArgs() {
    632603                String[] r = null;
    633                 if (this._browser.webview != null) {
     604                if (this._webView != null) {
    634605                        try {
    635                                 r = new String[] { this._browser.webEngine.getLocation() };
     606                                r = new String[] { this._webEngine.getLocation() };
    636607                        } catch (Exception e) {
    637608                                e.printStackTrace();
Note: See TracChangeset for help on using the changeset viewer.