Changeset 748


Ignore:
Timestamp:
01/24/14 11:32:31 (10 years ago)
Author:
ngw8
Message:

Changed JFX files to no longer use reflection (as some new features were impossible via reflection) and just import javafx instead. This will probably cause Eclipse to complain if you're using a Java version <= 7, but building/running Expeditee will still work (using Eclipse or Ant).
Have also added an Ant target that builds without ant JFX stuff. See the comments near the top of JfxBrowser.java or WebParser.java for details

Location:
trunk
Files:
1 added
1 deleted
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/build.xml

    r651 r748  
    4949                </fileset>
    5050        </path>
    51 
     51       
     52        <path id="classpath.jfx">
     53                <!-- Check this points to an existing file, if you can't find the jar just compile with build-nojfx -->
     54                <pathelement location="${java.home}/lib/jfxrt.jar"/>
     55        </path>
    5256
    5357        <target name="clean">
     
    6468                        <fileset dir="src">
    6569                                <exclude name="**/*.java"/>
    66                                 <exclude name="org/expeditee/items/widgets/WebBrowser.java"/>
    6770                        </fileset>
    6871                </copy>
     
    7376                </copy>
    7477        </target>
    75 
     78       
    7679        <target depends="init" name="build">
    7780                <javac source="${javac.source}" target="${javac.target}" debug="false"
    7881                       destdir="${build.dir.exp}" includeantruntime="false">                       
     82                       
    7983                        <src path="src"/>
    8084                        <src path="tests"/>
     85                       
    8186                        <exclude name="org/expeditee/items/widgets/WebBrowser.java"/>
     87               
     88                        <classpath>
     89                                <path refid="classpath.exp"/>
     90                               
     91                                <!-- jfxrt.jar path -->
     92                                <path refid="classpath.jfx"/>
     93                        </classpath>
     94                </javac>
     95        </target>
     96
     97        <target depends="init" name="build-nojfx">
     98                <javac source="${javac.source}" target="${javac.target}" debug="false"
     99                       destdir="${build.dir.exp}" includeantruntime="false">                       
     100                       
     101                        <src path="tests"/>
     102                        <src path="src"/>
     103                        <exclude name="org/expeditee/items/widgets/WebBrowser.java"/>
     104                       
     105                        <!-- Files that rely on JavaFX. Use build to build with them included -->
     106                        <exclude name="org/expeditee/items/widgets/JfxBrowser.java"/>
     107                        <exclude name="org/expeditee/io/WebParser.java"/>
     108                        <exclude name="org/expeditee/actions/JfxBrowserActions.java"/> 
     109                       
    82110                        <classpath refid="classpath.exp"/>
    83111                </javac>
    84112        </target>
     113       
     114
     115       
    85116        <target depends="build" name="jar">
    86117                <jar destfile="${dist.dir.exp}/${dist.filename.exp}" manifest="${manifest.path.exp}">
     
    117148        <target name="run">
    118149                <java classname="org.expeditee.gui.Browser" failonerror="true" fork="yes">
    119                         <classpath refid="classpath.exp"/>
    120150                        <classpath>
     151                                <path refid="classpath.exp"/>
     152                               
     153                                <!-- jfxrt.jar path -->
     154                                <path refid="classpath.jfx"/>
     155
    121156                                <pathelement location="${build.dir.exp}"/>
    122157                        </classpath>
  • trunk/src/org/expeditee/actions/Misc.java

    r722 r748  
    44import java.awt.Desktop;
    55import java.awt.Image;
    6 import java.awt.Polygon;
    76import java.awt.image.BufferedImage;
    87import java.awt.image.VolatileImage;
     
    2322
    2423import javax.imageio.ImageIO;
    25 import javax.script.ScriptEngine;
    26 import javax.script.ScriptEngineManager;
    27 import javax.script.ScriptException;
    2824
    2925import org.expeditee.gui.AttributeUtils;
     
    4238import org.expeditee.gui.TimeKeeper;
    4339import org.expeditee.importer.FrameDNDTransferHandler;
    44 import org.expeditee.io.WebParser;
    45 import org.expeditee.io.flowlayout.XGroupItem;
    4640import org.expeditee.items.Item;
    4741import org.expeditee.items.ItemUtils;
     
    5044import org.expeditee.items.XRayable;
    5145import org.expeditee.items.widgets.InteractiveWidget;
    52 import org.expeditee.items.widgets.JfxBrowser;
    5346import org.expeditee.items.widgets.WidgetCorner;
    5447import org.expeditee.items.widgets.WidgetEdge;
    5548import org.expeditee.math.ExpediteeJEP;
    56 import org.expeditee.settings.Settings;
    5749import org.expeditee.settings.UserSettings;
    58 import org.expeditee.settings.network.NetworkSettings;
    5950import org.expeditee.simple.SString;
    6051import org.expeditee.stats.CometStats;
     
    11111102        }
    11121103       
    1113         /**
    1114          * Launches items.widgets.JfxBrowser and uses Text item as URL.
    1115          * Note: currently doesn't work
    1116          * @param text Text item which passes contents as URL for browser.
    1117          * @throws Exception
    1118          */
    1119         public static void startBrowser(Item text) throws Exception {
    1120                 if (!(text instanceof Text)) {
    1121                         MessageBay.errorMessage("Must be a text item.");
    1122                         return;
    1123                 }
    1124                 if(text.getLink() != null) {
    1125                         MessageBay.errorMessage("Text item cannot have link.");
    1126                         return;
    1127                 }
    1128                        
    1129                 Text wt = new Text("@iw:org.expeditee.items.widgets.JfxBrowser");       // create new text item for browser widget
    1130                
    1131                 if(FreeItems.textOnlyAttachedToCursor()) {                      // navigates to url specified by the text item
    1132                         wt.appendText(":" + text.getText());
    1133                 } else {
    1134                         wt.appendText(":http://www.waikato.ac.nz");
    1135                 }
    1136                
    1137                 FreeItems.getInstance().clear();                                        // remove url text from cursor
    1138                
    1139                 wt.setParent(DisplayIO.getCurrentFrame());                      // set parent of text source for InteractiveWidget.createWidget()
    1140                 wt.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
    1141                 // create widget from text item
    1142                 JfxBrowser browser = (JfxBrowser) InteractiveWidget.createWidget(wt);
    1143                        
    1144                 FrameMouseActions.pickup(browser.getItems());           // attach browser widget to mouse
    1145         }
    1146        
    1147         /**
    1148          * Text item becomes link to new frame containing items.widgets.JfxBrowser and uses Text item as URL for browser.
    1149          * Note: currently doesn't work
    1150          * @param text Text item which passes contents as URL for browser and becomes link to the browser's new frame.
    1151          * @throws Exception
    1152          */
    1153         public static void startBrowserNewFrame(Item text) throws Exception {
    1154                 if (!(text instanceof Text)) {
    1155                         MessageBay.errorMessage("Must be a text item.");
    1156                         return;
    1157                 }
    1158                 if(text.getLink() != null) {                                            // text item can't already have a link
    1159                         MessageBay.errorMessage("Text item already has link.");
    1160                         return;
    1161                 }
    1162                
    1163                 // If no text with url is passed to action create a new text item with http://www.waikato.ac.nz for a default url
    1164                 if(!FreeItems.textOnlyAttachedToCursor()) {
    1165                         text = DisplayIO.getCurrentFrame().addText(FrameMouseActions.getX(), FrameMouseActions.getY(),
    1166                                         NetworkSettings.HomePage.get(), null);
    1167                         text.setParent(DisplayIO.getCurrentFrame());    // set parent of text source for InteractiveWidget.createWidget()
    1168                         FrameMouseActions.pickup(text);                                 // Attach new text link to cursor
    1169                 }
    1170                
    1171                 // Create JfxBrowser widget on a new frame
    1172                 Frame frame = FrameIO.CreateNewFrame(text);                     // create new frame for browser
    1173                 text.setLink("" + frame.getNumber());                           // link this text item to new frame
    1174                 // Create widget via text annotation
    1175                 Text wt = frame.addText(0, JfxBrowser.VERT_OFFSET, "@iw: org.expeditee.items.widgets.JfxBrowser "+ (Browser._theBrowser.getWidth() - JfxBrowser.HORZ_CROP)+
    1176                                  " " + (Browser._theBrowser.getHeight() - JfxBrowser.VERT_CROP) + " : ".concat(text.getText()), null);
    1177                 InteractiveWidget.createWidget(wt);
    1178                
    1179                 FrameIO.SaveFrame(frame);                                                       // save frame to disk
    1180         }
    1181        
    11821104        private static boolean startWidget(String name) throws Exception {
    11831105                String fullName = Actions.getClassName(name);
     
    12451167        }
    12461168       
    1247         public static void parsePage(Item text) throws Exception {
    1248                 if (!(text instanceof Text) || !FreeItems.textOnlyAttachedToCursor()) {
    1249                         MessageBay.errorMessage("Must provide a text item.");
    1250                         return;
    1251                 }
    1252                 if(text.getLink() != null) {                                            // text item can't already have a link
    1253                         MessageBay.errorMessage("Text item already has link.");
    1254                         return;
    1255                 }
    1256                
    1257                 // Create JfxBrowser widget on a new frame
    1258                 Frame frame = FrameIO.CreateNewFrame(text);                     // create new frame for browser
    1259                 text.setLink("" + frame.getNumber());                           // link this text item to new frame
    1260                 frame.addText(100, 100, "test", null);
    1261                
    1262                 WebParser.parseURL(text.getText(), frame);
    1263                 System.out.println(text.getText());
    1264         }
    1265        
    12661169        /**
    12671170         * Rebuilds the home frame restoring its original presentation.
     
    12741177                FrameUtils.CreateDefaultProfile(UserSettings.UserName.get(), homeFrame);
    12751178        }
    1276        
    1277         /**
    1278          * Adds a text item to the cursor which is linked to a new frame with the web browser active overlay and a JavaFX browser.
    1279          * @param text The text item attached to the cursor.
    1280          */
    1281         public static void startBrowserSession(Text text) {
    1282                 try {
    1283                         if (!(text instanceof Text)) {
    1284                                 MessageBay.errorMessage("Must be a text item.");
    1285                                 return;
    1286                         }
    1287                        
    1288                         if(text.getLink() != null) {                                            // text item can't already have a link
    1289                                 MessageBay.errorMessage("Text item already has link.");
    1290                                 return;
    1291                         }
    1292                        
    1293                         String url = "";
    1294                        
    1295                         // If no text with url is passed to action create a new text item
    1296                         if(!FreeItems.textOnlyAttachedToCursor()) {
    1297                                 url = NetworkSettings.HomePage.get();                                   // use home page specified by settings
    1298                                 text = DisplayIO.getCurrentFrame().addText(FrameMouseActions.getX(), FrameMouseActions.getY(),
    1299                                                 "Web Browser Session", null);
    1300                                 text.setParent(DisplayIO.getCurrentFrame());
    1301                                 FrameMouseActions.pickup(text);
    1302                         } else {
    1303                                 url = text.getText();                                                   // get url from text attached to cursor if possible
    1304                         }
    1305                        
    1306                         // Set text to session id. TODO: set session id.
    1307                         text.setText("Web Browser Session");
    1308                        
    1309                         // Create new frame
    1310                         Frame frame = FrameIO.CreateNewFrame(text);
    1311                         text.setLink("" + frame.getNumber());                           // link this text item to new frame
    1312                        
    1313                         // Remove everything from new page
    1314                         frame.removeAllItems(frame.getItems());
    1315                        
    1316                         // Add web browser active overlay
    1317                         frame.addText(1100, 50, "@ao: 2", null, "overlayset2");
    1318                         // Add @old
    1319                         frame.addText(1100, 20, "@old", null);
    1320                        
    1321                         // Create widget via text annotation
    1322                         Text wt = frame.addText(0, 80, "@iw: org.expeditee.items.widgets.JfxBrowser "+ (Browser._theBrowser.getWidth() - JfxBrowser.HORZ_CROP)+
    1323                                          " " + (Browser._theBrowser.getHeight() - JfxBrowser.VERT_CROP) + " : ".concat(url), null);
    1324                         InteractiveWidget.createWidget(wt);
    1325                        
    1326                         FrameIO.SaveFrame(frame);                                                       // save frame to disk
    1327                 } catch(Exception e) {
    1328                         e.printStackTrace();
    1329                 }
    1330         }
    1331        
     1179
    13321180        /**
    13331181         * Adds a text item to the cursor which is linked to a new frame with the mindmap active overlay.
     
    14631311        }
    14641312       
    1465         public static void gotoURL(Text link, String URL) {
    1466                 Frame frame = FrameIO.CreateNewFrame(link);
    1467                 link.setAction(null);
    1468                 link.setLink("" + frame.getNumber());
    1469                
    1470                 WebParser.parseURL(URL, frame);
    1471                
    1472                 frame.change();
    1473                
    1474                 FrameIO.SaveFrame(frame);
    1475         }
    1476        
    14771313        public static void testProgress() {
    14781314                new Thread(new Runnable() {
  • trunk/src/org/expeditee/io/WebParser.java

    r734 r748  
    1313import java.util.Arrays;
    1414
     15/*
     16 * 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.
     17 * 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),
     18 * or you can just exclude JfxBrowser, WebParser and JfxbrowserActions from the build path.
     19 *
     20 * If you are using Ant to build/run, 'ant build' will try to build with JavaFX jar added to the classpath.
     21 * If this fails, 'ant build-nojfx' will build with the JfxBrowser, WebParser and JfxbrowserActions excluded from the build path.
     22 */
     23
     24import javafx.animation.AnimationTimer;
     25import javafx.application.Platform;
     26import javafx.beans.value.ChangeListener;
     27import javafx.beans.value.ObservableValue;
     28import javafx.concurrent.Worker.State;
     29import javafx.scene.web.WebEngine;
     30
    1531import javax.imageio.ImageIO;
    1632import javax.swing.JComponent;
     33
     34import netscape.javascript.JSObject;
    1735
    1836import org.expeditee.gui.Frame;
     
    2644import org.expeditee.items.Picture;
    2745import org.expeditee.items.Text;
    28 import org.expeditee.reflection.JavaFX;
    2946import org.w3c.dom.Node;
    3047import org.w3c.dom.html.HTMLBodyElement;
     
    4966        public static void parseURL(final String URL, final Frame frame) {
    5067                try {
    51                         JavaFX.PlatformRunLater.invoke(null, new Runnable() {
     68                        Platform.runLater(new Runnable() {
    5269                                @Override
    5370                public void run() {
    5471                    try {
    55                         Object webEngine = JavaFX.WebEngineConstructor.newInstance(URL);
     72                                                WebEngine webEngine = new WebEngine(URL);
    5673                            loadPage(webEngine, frame);
    5774                    } catch (Exception e) {
     
    6582        }
    6683       
    67         protected static void loadPage(final Object webEngine, final Frame frame) throws Exception {
    68                 JavaFX.ReadOnlyObjectPropertyAddListener.invoke(JavaFX.WorkerStateProperty.invoke(JavaFX.WebEngineGetLoadWorker
    69                         .invoke(webEngine)), java.lang.reflect.Proxy.newProxyInstance(
    70                                         JavaFX.ChangeListener.getClassLoader(), new java.lang.Class[] { JavaFX.ChangeListener },
    71                         new java.lang.reflect.InvocationHandler() {
    72                         @Override
    73                         public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args)
    74                                 throws java.lang.Throwable {
    75                                 String method_name = method.getName();
    76                                 // Class<?>[] classes = method.getParameterTypes();
    77                                 // public void changed(ObservableValue ov, State oldState, State newState)
    78                                 if (method_name.equals("changed")) {
    79                                         // changed takes 3 args
    80                                         if (args == null || args.length != 3) {
    81                                                 return null;
    82                                         }
    83                                         // args[0] is the ObservableValue
    84                                         // args[2] is the new State
    85                                         if (args[2].getClass() == JavaFX.State) {
    86                                                 int id = JavaFX.StateConstants.indexOf(args[2]);
    87                                                 switch (id) {
    88                                                         case 0: // READY
    89                                                                 // MessageBay.displayMessage("WebEngine ready");
    90                                                                 break;
    91                                                         case 1: // SCHEDULED
    92                                                                 // MessageBay.displayMessage("Scheduled page load");
    93                                                                 break;
    94                                                         case 2: // RUNNING
    95                                                                 System.out.println("Loading page!");
    96                                                                 // MessageBay.displayMessage("WebEngine running");
    97                                                                 break;
    98                                                         case 3: // SUCCEEDED
    99                                                                 // MessageBay.displayMessage("Finished loading page");
    100                                                                 System.out.println("Parsing page!");
    101                                                                 JavaFX.WebEngineExecuteScript.invoke(webEngine, "window.resizeTo(800, 800);"
    102                                                                                 + "document.body.style.width = '1000px'");
    103                                                                 parsePage(webEngine, frame);
    104                                                                 System.out.println("Parsed page!");
    105                                                                 break;
    106                                                         case 4: // CANCELLED
    107                                                                 MessageBay.displayMessage("Cancelled loading page");
    108                                                                 break;
    109                                                         case 5: // FAILED
    110                                                                 MessageBay.displayMessage("Failed to load page");
    111                                                                 break;
    112                                                         }
    113                                                 }
    114                                                 System.out.println("\n");
    115                                         }
    116                                         return null;
    117                                 }
    118                 }));
     84        protected static void loadPage(final WebEngine webEngine, final Frame frame) throws Exception {
     85                webEngine.getLoadWorker().stateProperty().addListener(new ChangeListener<State>() {
     86
     87                        @Override
     88                        public void changed(ObservableValue<? extends State> ov, State oldState, State newState) {
     89
     90                        switch (newState) {
     91                                case READY: // READY
     92                                        // MessageBay.displayMessage("WebEngine ready");
     93                                        break;
     94                                case SCHEDULED: // SCHEDULED
     95                                        // MessageBay.displayMessage("Scheduled page load");
     96                                        break;
     97                                case RUNNING: // RUNNING
     98                                        System.out.println("Loading page!");
     99                                        // MessageBay.displayMessage("WebEngine running");
     100                                        break;
     101                                case SUCCEEDED: // SUCCEEDED
     102                                        // MessageBay.displayMessage("Finished loading page");
     103                                        System.out.println("Parsing page!");
     104                                        webEngine.executeScript("window.resizeTo(800, 800);"
     105                                                        + "document.body.style.width = '1000px'");
     106                                        parsePage(webEngine, frame);
     107                                        System.out.println("Parsed page!");
     108                                        break;
     109                                case CANCELLED: // CANCELLED
     110                                        MessageBay.displayMessage("Cancelled loading page");
     111                                        break;
     112                                case FAILED: // FAILED
     113                                        MessageBay.displayMessage("Failed to load page");
     114                                        break;
     115                        }       
     116                        }
     117                });
    119118        }
    120119       
     
    127126         *            The Expeditee frame to output the converted page to
    128127         */
    129         public static void parsePage(final Object webEngine, final Frame frame) {
     128        public static void parsePage(final WebEngine webEngine, final Frame frame) {
    130129                try {
    131                         JavaFX.PlatformRunLater.invoke(null, new Runnable() {
     130                        Platform.runLater(new Runnable() {
    132131                                @Override
    133132                                public void run() {
     
    135134                                                Progress progressBar = MessageBay.displayProgress("Converting web page");
    136135
    137                                                 HTMLBodyElement doc = (HTMLBodyElement) JavaFX.WebEngineExecuteScript.invoke(webEngine, "document.body");
    138 
    139                                                 Object window = JavaFX.WebEngineExecuteScript.invoke(webEngine, "window");
    140 
    141                                                 frame.setBackgroundColor(rgbStringToColor((String) JavaFX.JSObjectCall.invoke(JavaFX.JSObjectCall.invoke(window, "getComputedStyle", new Object[] { doc }), "getPropertyValue",
     136                                                Node doc = (Node) webEngine.executeScript("document.body");
     137
     138                                                JSObject window = (JSObject) webEngine.executeScript("window");
     139
     140                                                frame.setBackgroundColor(rgbStringToColor((String) ((JSObject) (window.call("getComputedStyle", new Object[] { doc }))).call("getPropertyValue",
    142141                                                                new Object[] { "background-color" })));
    143142                                               
    144143                                                // Functions to be used later in JavaScript
    145                                                 JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
     144                                                webEngine.executeScript(""
     145                                                                                + "function addToSpan(text) {"
     146                                                                                + "             span = document.createElement('wordSpan');"
     147                                                                                + "             span.textContent = text;"
     148                                                                                + "             par.insertBefore(span, refNode);"
     149                                                                                                // Checking if the current word is on a new line (i.e. lower than the previous word)
     150                                                                                + "             if (prevSpan !== null && span.getBoundingClientRect().top > prevSpan.getBoundingClientRect().top) {"
     151                                                                                                        // If it is, prepend a new line character to it. The new line characters doesn't affect the rendered HTML
     152                                                                                + "                     span.textContent = '\\n' + span.textContent;"
     153
     154                                                                                                        // Checking if the previous word is horizontally aligned with the one before it.
     155                                                                                                        // If it is, merge the text of the two spans
     156                                                                                + "                     if ( prevPrevSpan !== null && prevPrevSpan.getBoundingClientRect().left == prevSpan.getBoundingClientRect().left) {"
     157                                                                                + "                             prevPrevSpan.textContent = prevPrevSpan.textContent + prevSpan.textContent;"
     158                                                                                + "                             par.removeChild(prevSpan);"
     159                                                                                + "                     } else {"
     160                                                                                + "                             prevPrevSpan = prevSpan;"
     161                                                                                + "                     }"
     162                                                                                + "                     prevSpan = span;"
     163                                                                                + "             } else if ( prevSpan !== null) {"
     164                                                                                                        // Word is on the same line as the previous one, so merge the second into the span of the first
     165                                                                                + "                     prevSpan.textContent = prevSpan.textContent + span.textContent;"
     166                                                                                + "                     par.removeChild(span);"
     167                                                                                + "             } else {"
     168                                                                                + "                     prevSpan = span;"
     169                                                                                + "             }"
     170                                                                                + "}"
     171
     172                                                                                + "function splitIntoWords(toSplit) {"
     173                                                                                + "             var words = [];"
     174                                                                                + "             var pattern = /\\s+/g;"
     175                                                                                + "             var words = toSplit.split(pattern);"
     176                                                                                + ""
     177                                                                                + "             for (var i = 0; i < words.length - 1; i++) {"
     178                                                                                + "                     words[i] = words[i] + ' ';"
     179                                                                                + "             }"
     180                                                                                + "             return words;"
     181                                                                                + "}"
     182                                                );
     183                                       
     184                                                // Using Javascript to get an array of all the text nodes in the document so they can be wrapped in spans. Have to
     185                                                // loop through twice (once to build the array and once actually going through the array, otherwise when the
     186                                                // textnode is removed from the document items end up being skipped)
     187                                                JSObject textNodes = (JSObject) webEngine.executeScript(""
     188                                                        + "function getTextNodes(rootNode){"
     189                                                                + "var node;"
     190                                                                + "var textNodes=[];"
     191                                                                + "var walk = document.createTreeWalker(rootNode, NodeFilter.SHOW_TEXT);"
     192                                                                + "while(node=walk.nextNode()) {"
     193                                                                        + "if((node.textContent.trim().length > 0)) { "
     194                                                                                + "textNodes.push(node);"
     195                                                                        + "}"
     196                                                                + "}"
     197                                                                + "return textNodes;"
     198                                                        + "}; "
     199                                                        + "getTextNodes(document.body)"
     200                                                        );
     201                                               
     202                                                int nodesLength = (Integer) textNodes.getMember("length");
     203
     204                                                // Looping through all the text nodes in the document
     205                                                for (int j = 0; j < nodesLength; j++) {
     206                                                        Node currentNode = (Node) textNodes.getSlot(j);
     207
     208                                                        // Making the current node accessible in JavaScript
     209                                                        window.setMember("currentNode", currentNode);
     210                                               
     211                                                        webEngine.executeScript(""
     212                                                                        + "var span = null, prevSpan = null, prevPrevSpan = null;"
     213                                                                       
     214                                                                        // Removing repeated whitespace from the text node's content then splitting it into individual words
     215                                                                        + "var textContent  = currentNode.textContent.replace(/\\n|\\r/g, '').replace(/\\s+/g, ' ');"
     216                                                                        + "var words = splitIntoWords(textContent);"
     217                                                                       
     218                                                                        + "var refNode = currentNode.nextSibling;"
     219                                                                        + "var par = currentNode.parentElement;"
     220                                                                        + "currentNode.parentElement.removeChild(currentNode);"
     221                                                                       
     222                                                                        + "for (var i = 0; i < words.length; i++) {"
     223                                                                        + "             addToSpan(words[i]);"
     224                                                                        + "}"
     225                                                                       
     226                                                                        + "if (prevPrevSpan !== null && prevPrevSpan.getBoundingClientRect().left == prevSpan.getBoundingClientRect().left) {"
     227                                                                        + "             prevPrevSpan.textContent = prevPrevSpan.textContent + prevSpan.textContent;"
     228                                                                        + "             par.removeChild(prevSpan);"
     229                                                                        + "}"
     230                                                                        );
     231
     232                                                        // Will never reach 100% here, as the processing is not quite finished - progress is set to 100% at the end of
     233                                                        // the addPageToFrame loop below
     234                                                        progressBar.set((100 * (j)) / nodesLength);
     235                                                }
     236
     237                                                // Finding all links within the page, then setting the href attribute of all their descendants to be the same
     238                                                // link/URL.
     239                                                // This is needed because there is no apparent and efficient way to check if an element is a child of a link when
     240                                                // running through the document when added each element to Expeditee
     241                                                webEngine.executeScript(""
     242                                                                + "var anchors = document.getElementsByTagName('a');"
     243                                                                + ""
     244                                                                + "for (var i = 0; i < anchors.length; i++) {"
     245                                                                        + "var currentAnchor = anchors.item(i);"
     246                                                                        + "var anchorDescendants = currentAnchor.querySelectorAll('*');"
     247                                                                        + "for (var j = 0; j < anchorDescendants.length; j++) {"
     248                                                                                + "anchorDescendants.item(j).href = currentAnchor.href;"
     249                                                                        + "}"
     250                                                                + "}"
     251                                                                );
     252
     253                                                WebParser.addPageToFrame(doc, window, webEngine, frame);
     254
     255                                                progressBar.set(100);
     256
     257                                        } catch (Exception e) {
     258                                                e.printStackTrace();
     259                                        }
     260                                        System.out.println("Parsed frame");
     261                                        FrameUtils.Parse(frame);
     262                                        frame.setChanged(true);
     263                                        FrameIO.SaveFrame(frame);
     264                                }
     265                        });
     266                } catch (Exception e) {
     267                        e.printStackTrace();
     268                }
     269    }
     270
     271        /**
     272         * Converts a loaded page to Expeditee frame(s)
     273         *
     274         * @param webEngine
     275         *            The JavaFX WebEngine in which the page to be converted is loaded
     276         * @param frame
     277         *            The Expeditee frame to output the converted page to
     278         */
     279        public static void parsePageSimple(final WebEngine webEngine, final Object webView, final JComponent jfxPanel, final Frame frame) {
     280                try {
     281                        final Object notifier = new Object();
     282                        final MutableBool bottomReached = new MutableBool(false);
     283
     284                        final Progress progressBar = MessageBay.displayProgress("Converting web page");
     285
     286                        AnimationTimer timer = new AnimationTimer() {
     287
     288                                int frameCount = 0;
     289                                Frame frameToAddTo = frame;
     290
     291                                @Override
     292                                public void handle(long arg0) {
     293                                        // Must wait 2 frames before taking a snapshot of the webview, otherwise JavaFX won't have redrawn
     294                                        if (frameCount++ > 1) {
     295                                                frameCount = 0;
     296                                                this.stop();
     297
     298                                                BufferedImage image = new BufferedImage(jfxPanel.getWidth(), jfxPanel.getHeight(), BufferedImage.TYPE_INT_ARGB);
     299
     300                                                Graphics graphics = image.createGraphics();
     301
     302                                                // Drawing the JfxPanel (containing the webview) to the image
     303                                                jfxPanel.paint(graphics);
     304
     305                                                try {
     306                                                        int hashcode = Arrays.hashCode(image.getData().getPixels(0, 0, image.getWidth(), image.getHeight(), (int[]) null));
     307
     308                                                        File out = new File(FrameIO.IMAGES_PATH + "webpage-" + Integer.toHexString(hashcode) + ".png");
     309                                                        out.mkdirs();
     310                                                        ImageIO.write(image, "png", out);
     311
     312                                                        Text link = new Text("Next");
     313                                                        link.setPosition(500, 20);
     314                                                        frameToAddTo.addItem(link);
     315
     316                                                        FrameIO.SaveFrame(frameToAddTo);
     317
     318                                                        frameToAddTo = FrameIO.CreateFrame(frame.getFramesetName(), Integer.toHexString(hashcode), null);
     319
     320                                                        link.setLink(frameToAddTo.getName());
     321
     322                                                        // Adding the image
     323                                                        frameToAddTo.addText(0, 0, "@i: " + out.getName(), null);
     324
     325                                                        // Button to go to the next page
     326                                                        Text nextButton = (Text) FrameCreator.createButton("Next", null, null, 10F, 10F);
     327                                                        nextButton.setID(frameToAddTo.getNextItemID());
     328                                                        nextButton.addAction("next");
     329                                                        frameToAddTo.addItem(nextButton);
     330
     331                                                        FrameIO.SaveFrame(frameToAddTo);
     332                                                        System.out.println("C");
     333
     334                                                } catch (IOException e) {
     335                                                        e.printStackTrace();
     336                                                }
     337
     338
     339                                                graphics.dispose();
     340                                                image.flush();
     341
     342                                                synchronized (notifier) {
     343                                                        notifier.notify();
     344                                                }
     345
     346                                                try {
     347                                                        Platform.runLater(new Runnable() {
     348                                                                @Override
     349                                                                public void run() {
     350                                                                        try {
     351                                                                                HTMLBodyElement doc = (HTMLBodyElement) webEngine.executeScript("document.body");
     352
     353                                                                                JSObject window = (JSObject) webEngine.executeScript("window");
     354
     355                                                                                System.out.println("adding");
     356                                                                                WebParser.addPageToFrame(doc, window, webEngine, frameToAddTo);
     357                                                                        } catch (Exception ex) {
     358                                                                                ex.printStackTrace();
     359                                                                        }
     360                                                                }
     361                                                        });
     362                                                } catch (Exception ex) {
     363                                                        ex.printStackTrace();
     364                                                }
     365                                        }
     366                                }
     367                        };
     368
     369                        Platform.runLater(new Runnable() {
     370                                @Override
     371                                public void run() {
     372                                        try {
     373                                               
     374                                                webEngine.executeScript(""
     375                                                                // Initializing the counter used when scrolling the page
     376                                                                + "var scrollCounter = 0;"
     377                                                               
     378                                                                // Setting all text to be hidden
     379                                                                + "var css = document.createElement('style');"
     380                                                                + "css.type = 'text/css';"
     381                                                                + "var style = 'WordSpan { visibility: hidden }';"
     382                                                                + "css.appendChild(document.createTextNode(style));"
     383                                                                + "document.getElementsByTagName('head')[0].appendChild(css);");
     384
     385                                                HTMLBodyElement doc = (HTMLBodyElement) webEngine.executeScript("document.body");
     386
     387                                                JSObject window = (JSObject) webEngine.executeScript("window");
     388
     389                                                frame.setBackgroundColor(rgbStringToColor((String) ((JSObject) (window.call("getComputedStyle", new Object[] { doc }))).call("getPropertyValue",
     390                                                                new Object[] { "background-color" })));
     391                                               
     392                                                // Functions to be used later in JavaScript
     393                                                webEngine.executeScript(""
    146394                                                                                + "function addToSpan(text) {"
    147395                                                                                + "             span = document.createElement('wordSpan');"
     
    180428                                                // loop through twice (once to build the array and once actually going through the array, otherwise when the
    181429                                                // textnode is removed from the document items end up being skipped)
    182                                                 Object textNodes = JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
     430                                                JSObject textNodes = (JSObject) webEngine.executeScript(""
    183431                                                        + "function getTextNodes(rootNode){"
    184432                                                                + "var node;"
     
    195443                                                        );
    196444                                               
    197                                                 int nodesLength = (Integer) JavaFX.JSObjectGetMember.invoke(textNodes, "length");
     445                                                int nodesLength = (Integer) textNodes.getMember("length");
    198446
    199447                                                // Looping through all the text nodes in the document
    200448                                                for (int j = 0; j < nodesLength; j++) {
    201                                                         Node currentNode = (Node) JavaFX.JSObjectGetSlot.invoke(textNodes, j);
     449                                                        Node currentNode = (Node) textNodes.getSlot(j);
    202450
    203451                                                        // Making the current node accessible in JavaScript
    204                                                         JavaFX.JSObjectSetMember.invoke(window, "currentNode", currentNode);
     452                                                        window.setMember("currentNode", currentNode);
    205453                                               
    206                                                         JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
     454                                                        webEngine.executeScript(""
    207455                                                                        + "var span = null, prevSpan = null, prevPrevSpan = null;"
    208456                                                                       
     
    234482                                                // This is needed because there is no apparent and efficient way to check if an element is a child of a link when
    235483                                                // running through the document when added each element to Expeditee
    236                                                 JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
     484                                                webEngine.executeScript(""
    237485                                                                + "var anchors = document.getElementsByTagName('a');"
    238486                                                                + ""
     
    246494                                                                );
    247495
    248                                                 WebParser.addPageToFrame(doc, window, webEngine, frame);
    249 
    250                                                 progressBar.set(100);
    251 
    252                                         } catch (Exception e) {
    253                                                 e.printStackTrace();
    254                                         }
    255                                         System.out.println("Parsed frame");
    256                                         FrameUtils.Parse(frame);
    257                                         frame.setChanged(true);
    258                                         FrameIO.SaveFrame(frame);
    259                                 }
    260                         });
    261                 } catch (Exception e) {
    262                         e.printStackTrace();
    263                 }
    264     }
    265 
    266         /**
    267          * Converts a loaded page to Expeditee frame(s)
    268          *
    269          * @param webEngine
    270          *            The JavaFX WebEngine in which the page to be converted is loaded
    271          * @param frame
    272          *            The Expeditee frame to output the converted page to
    273          */
    274         public static void parsePageSimple(final Object webEngine, final Object webView, final JComponent jfxPanel, final Frame frame) {
    275                 try {
    276                         final Object notifier = new Object();
    277                         final MutableBool notAtBottom = new MutableBool(true);
    278 
    279                         JavaFX.PlatformRunLater.invoke(null, new Runnable() {
    280                                 @Override
    281                                 public void run() {
    282                                         try {
    283                                                 // Initializing the counter used when scrolling the page
    284                                                 JavaFX.WebEngineExecuteScript.invoke(webEngine, "var scrollCounter = 0");
    285496                                        } catch (Exception ex) {
    286497                                                ex.printStackTrace();
     
    303514                        }
    304515
    305                                 int tick = 0;
    306                                 Frame frameToAddTo = frame;
    307 
    308                         while (notAtBottom.getValue()) {
    309                                 JavaFX.PlatformRunLater.invoke(null, new Runnable() {
     516                        while (!bottomReached.getValue()) {
     517                                Platform.runLater(new Runnable() {
    310518                                        @Override
    311519                                        public void run() {
    312520                                                try {
    313521                                                        // Scrolling down the page
    314                                                         JavaFX.WebEngineExecuteScript.invoke(webEngine, ""
     522                                                        webEngine.executeScript(""
    315523                                                                        + "window.scrollTo(0, scrollCounter * window.innerHeight);"
    316524                                                                        + "scrollCounter = scrollCounter+1;");
    317                        
    318                                                         notAtBottom.setValue((Boolean) JavaFX.WebEngineExecuteScript.invoke(webEngine, "(window.pageYOffset + window.innerHeight < document.documentElement.scrollHeight)"));
     525
     526                                                        System.out.println('B');
     527
     528                                                        bottomReached.setValue((boolean) webEngine.executeScript("(window.pageYOffset + window.innerHeight >= document.documentElement.scrollHeight)"));
    319529
    320530                                                        synchronized (notifier) {
     
    338548                                }
    339549
    340                                 BufferedImage image = new BufferedImage(jfxPanel.getWidth(), jfxPanel.getHeight(), BufferedImage.TYPE_INT_ARGB);
    341 
    342                                 Graphics graphics = image.createGraphics();
    343 
    344                                 // Drawing the JfxPanel (containing the webview) to the image
    345                                 jfxPanel.paint(graphics);
    346 
    347                                 try {
    348                                         int hashcode = Arrays.hashCode(image.getData().getPixels(0, 0, image.getWidth(), image.getHeight(), (int[]) null));
    349 
    350                                         File out = new File(FrameIO.IMAGES_PATH + "webpage-" + Integer.toHexString(hashcode) + ".png");
    351                                         out.mkdirs();
    352                                         ImageIO.write(image, "png", out);
    353 
    354                                         Text link = new Text("Next");
    355                                         link.setPosition(500, 20);
    356                                         frameToAddTo.addItem(link);
    357 
    358                                         frameToAddTo = FrameIO.CreateFrame(frame.getFramesetName(), Integer.toHexString(hashcode), null);
    359 
    360                                         link.setLink(frameToAddTo.getName());
    361 
    362                                         // Adding the image
    363                                         frameToAddTo.addText(0, 0, "@i: " + out.getName(), null);
    364 
    365                                         // Button to go to the next page
    366                                         Text nextButton = (Text) FrameCreator.createButton("Next", null, null, 10F, 10F);
    367                                         nextButton.setID(frameToAddTo.getNextItemID());
    368                                         nextButton.addAction("next");
    369                                         frameToAddTo.addItem(nextButton);
    370 
    371                                         FrameIO.SaveFrame(frameToAddTo);
    372 
    373                                 } catch (IOException e) {
    374                                         e.printStackTrace();
     550                                timer.start();
     551
     552                                synchronized (notifier) {
     553                                        try {
     554                                                // Waiting for the timer thread to finish before looping again
     555                                                notifier.wait();
     556                                        } catch (InterruptedException e) {
     557                                                // TODO Auto-generated catch block
     558                                                e.printStackTrace();
     559                                        }
    375560                                }
    376                                 graphics.dispose();
    377                                 image.flush();
    378 
    379                                 System.out.println("C");
    380 
    381                                 synchronized (notifier) {
    382                                         notifier.notify();
    383                                 }
    384 
    385                                 tick = 0;
    386561
    387562                        }
     
    442617         * @throws IllegalAccessException
    443618         */
    444         private static void addPageToFrame(Node rootElement, Object window, Object webEngine, Frame frame) throws InvocationTargetException, IllegalAccessException,
     619        private static void addPageToFrame(Node rootElement, JSObject window, WebEngine webEngine, Frame frame) throws InvocationTargetException, IllegalAccessException,
    445620                        IllegalArgumentException {
    446621               
     
    449624                if (currentNode.getNodeType() == Node.TEXT_NODE || currentNode.getNodeType() == Node.ELEMENT_NODE) {
    450625                       
    451                         Object style;
    452                         Object bounds;
     626                        JSObject style;
     627                        JSObject bounds;
    453628
    454629                        if (currentNode.getNodeType() == Node.TEXT_NODE) {
    455630                                // CSS style for the element
    456                                 style = JavaFX.JSObjectCall.invoke(window, "getComputedStyle", new Object[] { currentNode.getParentNode() });
     631                                style = (JSObject) window.call("getComputedStyle", new Object[] { currentNode.getParentNode() });
    457632
    458633                                // Getting a rectangle that represents the area and position of the element
    459                                 bounds = JavaFX.JSObjectCall.invoke(currentNode.getParentNode(), "getBoundingClientRect", new Object[] {});
     634                                bounds = (JSObject) ((JSObject) currentNode.getParentNode()).call("getBoundingClientRect", new Object[] {});
    460635                        } else {
    461                                 style = JavaFX.JSObjectCall.invoke(window, "getComputedStyle", new Object[] { currentNode });
    462 
    463                                 bounds = JavaFX.JSObjectCall.invoke(currentNode, "getBoundingClientRect", new Object[] {});
     636                                style = (JSObject) window.call("getComputedStyle", new Object[] { currentNode });
     637
     638                                bounds = (JSObject) ((JSObject) currentNode).call("getBoundingClientRect", new Object[] {});
    464639                        }
    465640                       
     
    467642                        // TODO: This doesn't check if an element or any of its parent elements have position:fixed set - the only
    468643                        // way to check seems to be to walking through the element's parents until the document root is reached
    469                         float x = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "left").toString())
    470                                         + Float.valueOf(JavaFX.WebEngineExecuteScript.invoke(webEngine, "window.pageXOffset").toString());
    471                         float y = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "top").toString())
    472                                         + Float.valueOf(JavaFX.WebEngineExecuteScript.invoke(webEngine, "window.pageYOffset").toString());
    473 
    474                         float width = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "width").toString());
    475                         float height = Float.valueOf(JavaFX.JSObjectGetMember.invoke(bounds, "height").toString());
     644                        float x = Float.valueOf(bounds.getMember("left").toString()) + Float.valueOf(webEngine.executeScript("window.pageXOffset").toString());
     645                        float y = Float.valueOf(bounds.getMember("top").toString()) + Float.valueOf(webEngine.executeScript("window.pageYOffset").toString());
     646
     647                        float width = Float.valueOf(bounds.getMember("width").toString());
     648                        float height = Float.valueOf(bounds.getMember("height").toString());
    476649
    477650                        // Checking if the element is actually visible on the page
     
    480653                                // Filtering the node type, starting with text nodes
    481654                                if (currentNode.getNodeType() == Node.TEXT_NODE) {
    482                                         String fontSize = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-size" }));
     655                                       
     656                                        String fontSize = ((String) style.call("getPropertyValue", new Object[] { "font-size" }));
    483657
    484658                                        // Trimming off the units (always px) from the font size
     
    486660                                       
    487661                                        // Always returns in format "rgb(x,x,x)" or "rgba(x,x,x,x)"
    488                                         String color = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "color" });
     662                                        String color = (String) style.call("getPropertyValue", new Object[] { "color" });
    489663                                       
    490664                                        // Always returns in format "rgb(x,x,x)" or "rgba(x,x,x,x)"
    491                                         String bgColorString = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-color" });
    492 
    493                                         String align = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "text-align" });
     665                                        String bgColorString = (String) style.call("getPropertyValue", new Object[] { "background-color" });
     666
     667                                        String align = (String) style.call("getPropertyValue", new Object[] { "text-align" });
    494668                                       
    495669                                        // Returns comma-separated list of typefaces
    496                                         String typeface = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-family" });
     670                                        String typeface = (String) style.call("getPropertyValue", new Object[] { "font-family" });
    497671
    498672                                        String[] typefaces = typeface.split(", |,");
    499673                                       
    500                                         String weight = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-weight" });
     674                                        String weight = (String) style.call("getPropertyValue", new Object[] { "font-weight" });
    501675                                       
    502                                         String fontStyle = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "font-style" });
     676                                        String fontStyle = (String) style.call("getPropertyValue", new Object[] { "font-style" });
    503677
    504678                                        // Returns "normal" or a value in pixels (e.g. "10px")
    505                                         String letterSpacing = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "letter-spacing" });
     679                                        String letterSpacing = (String) style.call("getPropertyValue", new Object[] { "letter-spacing" });
    506680
    507681                                        // Returns a value in pixels (e.g. "10px")
    508                                         String lineHeight = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "line-height" });
    509 
    510                                         String textTransform = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "text-transform" });
    511 
    512                                         String linkUrl = (String) JavaFX.JSObjectGetMember.invoke(currentNode.getParentNode(), "href");
     682                                        String lineHeight = (String) style.call("getPropertyValue", new Object[] { "line-height" });
     683
     684                                        String textTransform = (String) style.call("getPropertyValue", new Object[] { "text-transform" });
     685
     686                                        String linkUrl = (String) ((JSObject) currentNode.getParentNode()).getMember("href");
    513687
    514688                                        Boolean fontFound = false;
     
    632806
    633807                                        // Always returns in format "rgb(x,x,x)" or "rgba(x,x,x,x)"
    634                                         String bgColorString = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-color" });
     808                                        String bgColorString = (String) style.call("getPropertyValue", new Object[] { "background-color" });
    635809
    636810                                        Color bgColor = rgbStringToColor(bgColorString);
     
    645819                                        // may also return gradients, data, etc. (not handled yet). Only need to add bg image on
    646820                                        // 'ELEMENT_NODE' (and not 'TEXT_NODE' otherwise there would be double-ups
    647                                         String bgImage = (String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-image" });
     821                                        String bgImage = (String) style.call("getPropertyValue", new Object[] { "background-image" });
    648822                                       
    649                                         String linkUrl = (String) JavaFX.JSObjectGetMember.invoke(currentNode, "href");
     823                                        String linkUrl = (String) ((JSObject) currentNode).getMember("href");
    650824
    651825                                        if (bgImage.startsWith("url(")) {
    652826                                                bgImage = bgImage.substring(4, bgImage.length() - 1);
    653827
    654                                                 String bgSize = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-size" })).toLowerCase();
    655                                                 String bgRepeat = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-repeat" })).toLowerCase();
     828                                                String bgSize = ((String) style.call("getPropertyValue", new Object[] { "background-size" })).toLowerCase();
     829                                                String bgRepeat = ((String) style.call("getPropertyValue", new Object[] { "background-repeat" })).toLowerCase();
    656830
    657831                                                // Returns "[x]px [y]px", "[x]% [y]%", "[x]px [y]%" or "[x]% [y]px"
    658                                                 String bgPosition = ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "background-position" })).toLowerCase();
     832                                                String bgPosition = ((String) style.call("getPropertyValue", new Object[] { "background-position" })).toLowerCase();
    659833
    660834                                                String[] bgOffsetCoords = bgPosition.split(" ");
     
    720894                                        String imgSrc;
    721895
    722                                         if (currentNode.getNodeName().toLowerCase().equals("img") && (imgSrc = JavaFX.JSObjectGetMember.invoke(currentNode, "src").toString()) != null) {
     896                                        if (currentNode.getNodeName().toLowerCase().equals("img") && (imgSrc = ((JSObject) currentNode).getMember("src").toString()) != null) {
    723897                                                try {
    724898                                                        WebParser.addImageFromUrl(imgSrc, linkUrl, frame, x, y, (int) width, null, null, null, null, null, 0, 0);
     
    743917        }
    744918
    745         private static boolean elementVisible(float x, float y, float width, float height, Object style) {
     919        private static boolean elementVisible(float x, float y, float width, float height, JSObject style) {
    746920                try {
    747                         if (width <= 0 || height <= 0 || x + width <= 0 || y + height <= 0 || ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "visibility" })).equals("hidden")
    748                                         || ((String) JavaFX.JSObjectCall.invoke(style, "getPropertyValue", new Object[] { "display" })).equals("none")) {
     921                        if (width <= 0 || height <= 0 || x + width <= 0 || y + height <= 0 || ((String) style.call("getPropertyValue", new Object[] { "visibility" })).equals("hidden")
     922                                        || ((String) style.call("getPropertyValue", new Object[] { "display" })).equals("none")) {
    749923                                return false;
    750924                        } else {
  • trunk/src/org/expeditee/items/widgets/JfxBrowser.java

    r733 r748  
    1717import java.awt.event.MouseListener;
    1818import java.awt.event.MouseMotionListener;
    19 import java.lang.reflect.InvocationTargetException;
     19
     20/*
     21 * 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.
     22 * 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),
     23 * or you can just exclude JfxBrowser, WebParser and JfxbrowserActions from the build path.
     24 *
     25 * If you are using Ant to build/run, 'ant build' will try to build with JavaFX jar added to the classpath.
     26 * If this fails, 'ant build-nojfx' will build with the JfxBrowser, WebParser and JfxbrowserActions excluded from the build path.
     27 */
     28
     29import javafx.application.Platform;
     30import javafx.beans.value.ChangeListener;
     31import javafx.beans.value.ObservableValue;
     32import javafx.concurrent.Worker.State;
     33import javafx.embed.swing.JFXPanel;
     34import javafx.event.EventHandler;
     35import javafx.scene.Scene;
     36import javafx.scene.web.WebEngine;
     37import javafx.scene.web.WebView;
    2038
    2139import javax.swing.JButton;
     
    3553import org.expeditee.items.Item;
    3654import org.expeditee.items.Text;
    37 import org.expeditee.reflection.JavaFX;
    3855import org.expeditee.settings.network.NetworkSettings;
    3956
     
    5673       
    5774        private WebBrowserPanel _browser;
    58        
    59         /**
    60          * ID of the mouse button that is currently pressed. Uses {@link MouseEvent} constants
    61          */
    62         private int buttonDownId;
     75
     76        static {
     77                Platform.setImplicitExit(false);
     78        }
    6379
    6480        private static class WebBrowserPanel extends JPanel implements ComponentListener {
     
    6682                private static final long serialVersionUID = 1L;
    6783
    68                 Object webview;
    69                 Object jfxPanel;
     84                WebView webview;
     85                WebEngine webEngine;
     86                JFXPanel jfxPanel;
    7087                JfxBrowser owner;
    7188
     
    87104                        this.addComponentListener(this);
    88105                        try {
    89                                 jfxPanel = JavaFX.JFXPanel.newInstance();
     106                                jfxPanel = new JFXPanel();
    90107
    91108                                // Toolbar (that can't be dragged) to hold the nav buttons, url bar, etc
     
    258275                                this.add((Component) jfxPanel);
    259276
    260                                 JavaFX.PlatformRunLater.invoke(null, new Runnable() {
     277                                Platform.runLater(new Runnable() {
    261278                                        @Override
    262279                                        public void run() {
     
    287304                private void initFx(String url) {
    288305                        try {
    289                                 this.webview = JavaFX.WebView.newInstance();
    290 
    291                                 Object scene = JavaFX.SceneConstructor.newInstance(this.webview);
    292 
    293                                 JavaFX.JFXPanelSetScene.invoke(jfxPanel, scene);
    294 
    295                                 JavaFX.ReadOnlyObjectPropertyAddListener.invoke(JavaFX.WorkerStateProperty.invoke(JavaFX.WebEngineGetLoadWorker
    296                                         .invoke(JavaFX.WebViewGetEngine.invoke(this.webview))), java.lang.reflect.Proxy.newProxyInstance(
    297                                                         JavaFX.ChangeListener.getClassLoader(), new java.lang.Class[] { JavaFX.ChangeListener },
    298                                         new java.lang.reflect.InvocationHandler() {
    299                                                 @Override
    300                                                 public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args)
    301                                                         throws java.lang.Throwable {
    302                                                         String method_name = method.getName();
    303                                                         // Class<?>[] classes = method.getParameterTypes();
    304                                                         // public void changed(ObservableValue ov, State oldState, State newState)
    305                                                         if (method_name.equals("changed")) {
    306                                                                 // changed takes 3 args
    307                                                                 if (args == null || args.length != 3) {
    308                                                                         return null;
    309                                                                 }
    310                                                                 // args[0] is the ObservableValue
    311                                                                 System.out.println(args[0]);
    312                                                                 System.out.println(args[0].getClass());
    313                                                                 // args[2] is the new State
    314                                                                 if (args[2].getClass() == JavaFX.State) {
    315                                                                         int id = JavaFX.StateConstants.indexOf(args[2]);
    316                                                                         switch (id) {
    317                                                                                 case 0: // READY
    318                                                                                         MessageBay.displayMessage("WebEngine ready");
    319                                                                                         break;
    320                                                                                 case 1: // SCHEDULED
    321                                                                                         MessageBay.displayMessage("Scheduled page load");
    322                                                                                         break;
    323                                                                                 case 2: // RUNNING
    324                                                                                         MessageBay.displayMessage("WebEngine running");
    325 
    326                                                                                         // Updating the URL bar to display the URL of the page being loaded
    327                                                                                         WebBrowserPanel.this.urlField.setText((String) JavaFX.WebEngineGetLocation.invoke(JavaFX.WebViewGetEngine.invoke(WebBrowserPanel.this.webview)));
    328                                                                                         break;
    329                                                                                 case 3: // SUCCEEDED
    330                                                                                         MessageBay.displayMessage("Finished loading page");
    331                                                                                         break;
    332                                                                                 case 4: // CANCELLED
    333                                                                                         MessageBay.displayMessage("Cancelled loading page");
    334                                                                                         break;
    335                                                                                 case 5: // FAILED
    336                                                                                         MessageBay.displayMessage("Failed to load page");
    337                                                                                         break;
    338                                                                                 }
    339                                                                         }
    340                                                                         System.out.println("\n");
    341                                                                 }
    342                                                                 return null;
    343                                                         }
    344                                         }));
     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                                });
    345345                               
    346346                                // Captures mouse click events on webview to enable expeditee like behavior for JavaFX browser.
    347                                 JavaFX.NodeSetOnMouseClicked.invoke(this.webview, java.lang.reflect.Proxy.newProxyInstance(
    348                                                 JavaFX.EventHandler.getClassLoader(), new java.lang.Class[] { JavaFX.EventHandler },
    349                                         new java.lang.reflect.InvocationHandler() {
    350                                                 @Override
    351                                                 public Object invoke(Object proxy, java.lang.reflect.Method method, Object[] args)
    352                                                         throws java.lang.Throwable {
    353                                                        
    354                                                         if(method.getName().equals("handle")) {
    355                                                                 // Gets button clicked enum values
    356                                                                 Object[] buttonEnum = JavaFX.MouseButton.getEnumConstants();
    357                                                                
    358                                                                 if(JavaFX.MouseEventGetButton.invoke(args[0]).equals(buttonEnum[1])) /* Left Mouse Button */ {
    359                                                                        
    360                                                                 } else if(JavaFX.MouseEventGetButton.invoke(args[0]).equals(buttonEnum[2])) /* Middle Mouse Button */ {
    361                                                                        
    362                                                                 } else if(JavaFX.MouseEventGetButton.invoke(args[0]).equals(buttonEnum[3])) /* Right Mouse Button */ {
    363                                                                         // Gets text currently selected in webview
    364                                                                         String selection = (String) JavaFX.WebEngineExecuteScript.invoke(JavaFX.WebViewGetEngine.invoke(webview), "window.getSelection().toString()");
    365 
    366                                                                         // Do nothing if no text is selected
    367                                                                         if(!selection.equals("")) {
    368                                                                                 // Copy text and attach to cursor
    369                                                                                         Text t = new Text(selection);
    370                                                                                         t.setParent(DisplayIO.getCurrentFrame());
    371                                                                                         t.setXY(FrameMouseActions.getX(), FrameMouseActions.getY());
    372                                                                                         FrameMouseActions.pickup(t);
    373                                                                         }
    374                                                                 }
    375                                                         }
    376                                                        
    377                                                                 return null;
     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);
    378362                                                        }
    379                                         }));
     363
     364                                                        break;
     365                                                }
     366                                        }
     367                                });
    380368
    381369                                // Disables JavaFX webview's right click menu
    382                                 JavaFX.WebViewSetContextMenuEnabled.invoke(this.webview, false);
    383                                
    384                                 // webEngine.getLoadWorker().stateProperty().addListener(
    385                                 // new ChangeListener<State>() {
    386                                 // public void changed(ObservableValue ov, State oldState, State newState) {
    387                                 // if (newState == State.SUCCEEDED) {
    388                                 // stage.setTitle(webEngine.getLocation());
    389                                 // }
    390                                 // }
    391                                 // });
    392 
    393                                 JavaFX.WebEngineLoad.invoke(JavaFX.WebViewGetEngine.invoke(this.webview), url);
     370                                this.webview.setContextMenuEnabled(false);
     371
     372                                this.webEngine.load(url);
    394373                        } catch (Exception e) {
    395374                                e.printStackTrace();
     
    455434                System.out.println(actualURL);
    456435                try {
    457                         JavaFX.PlatformRunLater.invoke(null, new Runnable() {
     436                        Platform.runLater(new Runnable() {
    458437                                @Override
    459438                                public void run() {
    460439                                        try {
    461                                                 JavaFX.WebEngineLoad.invoke(JavaFX.WebViewGetEngine.invoke(JfxBrowser.this._browser.webview), actualURL);
     440                                                JfxBrowser.this._browser.webEngine.load(actualURL);
    462441                                        } catch (Exception e) {
    463442                                                e.printStackTrace();
     
    476455        public void navigateBack() {
    477456                try {
    478                         final Object webEngine = JavaFX.WebViewGetEngine.invoke(this._browser.webview);
    479                         try {
    480                                 JavaFX.PlatformRunLater.invoke(null, new Runnable() {
    481                                         @Override
    482                                         public void run() {
    483                                                 try {
    484                                                         JavaFX.WebHistoryGo.invoke(JavaFX.WebEngineGetHistory.invoke(webEngine), -1);
    485                                                         FreeItems.getInstance().clear();
    486                                                 } catch (InvocationTargetException e) {
    487                                                         MessageBay.displayMessage("Start of History");
    488                                                 } catch (Exception e) {
    489                                                         e.printStackTrace();
    490                                                 }
    491                                         }
    492                                 });
    493                         } catch (Exception e) {
    494                                 e.printStackTrace();
    495                         }
     457                Platform.runLater(new Runnable() {
     458                        @Override
     459                        public void run() {
     460                                try {
     461                                        JfxBrowser.this._browser.webEngine.getHistory().go(-1);
     462                                        FreeItems.getInstance().clear();
     463                                } catch (IndexOutOfBoundsException e) {
     464                                        MessageBay.displayMessage("Start of History");
     465                                        }
     466                        }
     467                });
    496468                } catch (Exception e) {
    497469                        e.printStackTrace();
     
    505477        public void navigateForward() {
    506478                try {
    507                         final Object webEngine = JavaFX.WebViewGetEngine.invoke(this._browser.webview);
    508                         try {
    509                                 JavaFX.PlatformRunLater.invoke(null, new Runnable() {
    510                                         @Override
    511                                         public void run() {
    512                                                 try {
    513                                                         JavaFX.WebHistoryGo.invoke(JavaFX.WebEngineGetHistory.invoke(webEngine), 1);
    514                                                         FreeItems.getInstance().clear();
    515                                                 } catch (InvocationTargetException e) {
    516                                                         MessageBay.displayMessage("End of History");
    517                                                 } catch (Exception e) {
    518                                                         e.printStackTrace();
    519                                                 }
    520                                         }
    521                                 });
    522                         } catch (Exception e) {
    523                                 e.printStackTrace();
    524                         }
     479                Platform.runLater(new Runnable() {
     480                        @Override
     481                        public void run() {
     482                                try {
     483                                        JfxBrowser.this._browser.webEngine.getHistory().go(1);
     484                                        FreeItems.getInstance().clear();
     485                                } catch (IndexOutOfBoundsException e) {
     486                                        MessageBay.displayMessage("End of History");
     487                                        }
     488                        }
     489                });
    525490                } catch (Exception e) {
    526491                        e.printStackTrace();
     
    533498        public void refresh() {
    534499                try {
    535                         final Object webEngine = JavaFX.WebViewGetEngine.invoke(this._browser.webview);
    536                         try {
    537                                 JavaFX.PlatformRunLater.invoke(null, new Runnable() {
    538                                         @Override
    539                                         public void run() {
    540                                                 try {
    541                                                         JavaFX.WebEngineReload.invoke(webEngine);
    542                                                         FreeItems.getInstance().clear();
    543                                                         MessageBay.displayMessage("Page Refreshing");
    544                                                 } catch (Exception e) {
    545                                                         e.printStackTrace();
    546                                                 }
    547                                         }
    548                                 });
    549                         } catch (Exception e) {
    550                                 e.printStackTrace();
    551                         }
     500                Platform.runLater(new Runnable() {
     501                        @Override
     502                        public void run() {
     503                                try {
     504                                        JfxBrowser.this._browser.webEngine.reload();
     505                                        FreeItems.getInstance().clear();
     506                                        MessageBay.displayMessage("Page Reloading");
     507                                } catch (Exception e) {
     508                                        e.printStackTrace();
     509                                }
     510                        }
     511                });
    552512                } catch (Exception e) {
    553513                        e.printStackTrace();
    554514                }
     515
    555516        }
    556517       
     
    560521        public void getFrame() {
    561522                try {
    562                         WebParser.parsePage(JavaFX.WebViewGetEngine.invoke(this._browser.webview), DisplayIO.getCurrentFrame());
     523                        WebParser.parsePage(this._browser.webEngine, DisplayIO.getCurrentFrame());
    563524                } catch (Exception e) {
    564525                        e.printStackTrace();
     
    572533                // this.layout(this._browser);
    573534                try {
    574                         WebParser.parsePageSimple(JavaFX.WebViewGetEngine.invoke(this._browser.webview), this._browser.webview, (JComponent) this._browser.jfxPanel, DisplayIO.getCurrentFrame());
     535                        WebParser.parsePageSimple(this._browser.webEngine, this._browser.webview, (JComponent) this._browser.jfxPanel, DisplayIO.getCurrentFrame());
    575536                } catch (Exception e) {
    576537                        e.printStackTrace();
     
    672633                if (this._browser.webview != null) {
    673634                        try {
    674                                 r = new String[] { (String) JavaFX.WebEngineGetLocation.invoke(JavaFX.WebViewGetEngine.invoke(this._browser.webview)) };
     635                                r = new String[] { this._browser.webEngine.getLocation() };
    675636                        } catch (Exception e) {
    676637                                e.printStackTrace();
Note: See TracChangeset for help on using the changeset viewer.