/* This file is part of RouteConverter. RouteConverter is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. RouteConverter is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with RouteConverter; if not, write to the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA Copyright (C) 2007 Christian Pesch. All Rights Reserved. */ package slash.navigation.mapview.browser; import chrriis.dj.nativeswing.swtimpl.components.*; import slash.navigation.common.NavigationPosition; import java.awt.*; import java.lang.reflect.InvocationTargetException; import java.util.logging.Logger; import static chrriis.dj.nativeswing.swtimpl.NativeInterface.isOpen; import static chrriis.dj.nativeswing.swtimpl.components.JWebBrowser.useWebkitRuntime; import static chrriis.dj.nativeswing.swtimpl.components.JWebBrowser.useXULRunnerRuntime; import static java.lang.Boolean.parseBoolean; import static java.lang.System.currentTimeMillis; import static javax.swing.SwingUtilities.invokeAndWait; import static javax.swing.SwingUtilities.isEventDispatchThread; import static slash.common.helpers.ThreadHelper.invokeInAwtEventQueue; import static slash.common.io.Transfer.parseDouble; import static slash.common.system.Platform.isLinux; /** * Implementation for a component that displays the positions of a position list on a map * using the Eclipse SWT Webbrowser embedding in the DJNative Swing JWebBrowser. * * @author Christian Pesch */ public class EclipseSWTMapView extends BrowserMapView { private static final Logger log = Logger.getLogger(EclipseSWTMapView.class.getName()); private JWebBrowser webBrowser; public Component getComponent() { return webBrowser; } // initialization private JWebBrowser createWebBrowser() { try { if (!isOpen()) throw new Exception("Native Interface is not initialized"); JWebBrowser browser; if (isLinux()) { try { System.setProperty("org.eclipse.swt.browser.UseWebKitGTK", "true"); browser = new JWebBrowser(useWebkitRuntime()); log.info("Using WebKit runtime to create WebBrowser"); } catch (IllegalStateException e) { System.clearProperty("org.eclipse.swt.browser.UseWebKitGTK"); browser = new JWebBrowser(useXULRunnerRuntime()); log.info("Using XULRunner runtime to create WebBrowser: " + e); } } else { browser = new JWebBrowser(); } browser.setBarsVisible(false); browser.setJavascriptEnabled(true); browser.addWebBrowserListener(new WebBrowserListener() { public void windowWillOpen(WebBrowserWindowWillOpenEvent e) { log.fine("WebBrowser windowWillOpen " + e.isConsumed() + " thread " + Thread.currentThread()); } public void windowOpening(WebBrowserWindowOpeningEvent e) { log.fine("WebBrowser windowOpening " + e.getLocation() + "/" + e.getSize() + " thread " + Thread.currentThread()); } public void windowClosing(WebBrowserEvent e) { log.fine("WebBrowser windowClosing " + e + " thread " + Thread.currentThread()); } public void locationChanging(WebBrowserNavigationEvent e) { log.fine("WebBrowser locationChanging " + e.getNewResourceLocation() + " thread " + Thread.currentThread()); } public void locationChanged(WebBrowserNavigationEvent e) { log.fine("WebBrowser locationChanged " + e.getNewResourceLocation() + " thread " + Thread.currentThread()); } public void locationChangeCanceled(WebBrowserNavigationEvent e) { log.fine("WebBrowser locationChangeCanceled " + e.getNewResourceLocation() + " thread " + Thread.currentThread()); } private int startCount = 0; public void loadingProgressChanged(WebBrowserEvent e) { log.fine("WebBrowser loadingProgressChanged " + e.getWebBrowser().getLoadingProgress() + " thread " + Thread.currentThread()); if (e.getWebBrowser().getLoadingProgress() == 100 && startCount == 0) { // get out of the listener callback new Thread(new Runnable() { public void run() { tryToInitialize(startCount++, currentTimeMillis()); } }, "MapViewInitializer").start(); } } public void titleChanged(WebBrowserEvent e) { log.fine("WebBrowser titleChanged " + e.getWebBrowser().getPageTitle() + " thread " + Thread.currentThread()); } public void statusChanged(WebBrowserEvent e) { log.fine("WebBrowser statusChanged " + e.getWebBrowser().getStatusText() + " thread " + Thread.currentThread()); } public void commandReceived(WebBrowserCommandEvent e) { // log.fine("WebBrowser commandReceived " + e.getCommand() + " thread " + Thread.currentThread()); } }); return browser; } catch (Throwable t) { log.severe("Cannot create WebBrowser: " + t); setInitializationCause(t); return null; } } private boolean loadWebPage() { try { final String url = prepareWebPage(); webBrowser.runInSequence(new Runnable() { public void run() { webBrowser.navigate(url); } }); } catch (Throwable t) { log.severe("Cannot load web page: " + t); setInitializationCause(t); return false; } return true; } protected void initializeBrowser() { webBrowser = createWebBrowser(); if (webBrowser == null) return; log.info("Using Eclipse SWT Browser to create map view"); initializeWebPage(); } protected void initializeWebPage() { log.info("Loading Google Maps API from " + getGoogleMapsServerApiUrl()); if (!loadWebPage()) dispose(); } protected boolean isMapInitialized() { String result = executeScriptWithResult("return isInitialized();"); return parseBoolean(result); } // bounds and center protected NavigationPosition getNorthEastBounds() { return parsePosition("return getNorthEastBounds();"); } protected NavigationPosition getSouthWestBounds() { return parsePosition("return getSouthWestBounds();"); } protected NavigationPosition getCurrentMapCenter() { return parsePosition("return getCenter();"); } protected Integer getCurrentZoom() { Double zoom = parseDouble(executeScriptWithResult("return getZoom();")); return zoom != null ? zoom.intValue() : null; } protected String getCallbacks() { return executeScriptWithResult("return getCallbacks();"); } public boolean isSupportsPrinting() { return true; } public boolean isSupportsPrintingWithDirections() { return true; } public void print(String title, boolean withDirections) { executeScript("printMap(\"" + title + "\", " + withDirections + ");"); } // script execution protected void executeScript(final String script) { if (webBrowser == null || script.length() == 0) return; invokeInAwtEventQueue(new Runnable() { public void run() { webBrowser.runInSequence(new Runnable() { public void run() { webBrowser.executeJavascript(script); } }); logJavaScript(script, null); } }); } protected String executeScriptWithResult(final String script) { if (script.length() == 0) return null; final boolean debug = preferences.getBoolean(DEBUG_PREFERENCE, false); final boolean pollingCallback = !script.contains("getCallbacks"); final Object[] result = new Object[1]; if (!isEventDispatchThread()) { try { invokeAndWait(new Runnable() { public void run() { webBrowser.runInSequence(new Runnable() { public void run() { result[0] = webBrowser.executeJavascriptWithResult(script); if (debug && pollingCallback) { log.info("After invokeLater, executeJavascriptWithResult " + result[0]); } } }); } }); } catch (InterruptedException | InvocationTargetException e) { log.severe("Cannot execute script with result: " + e); } } else { webBrowser.runInSequence(new Runnable() { public void run() { result[0] = webBrowser.executeJavascriptWithResult(script); if (debug && pollingCallback) { log.info("After executeJavascriptWithResult " + result[0]); } } }); } if (pollingCallback) { logJavaScript(script, result[0]); } return result[0] != null ? result[0].toString() : null; } }