Browse Source

Fixed no Internet connection bug in SymbolLayer

- when switched to symbolLayer without Internet connection, warning msg

- when in symbolLayer and Internet connection is lost, load tiles from
chache
dominik 8 years ago
parent
commit
6266a9adfe

+ 36 - 2
scopviz/src/main/java/de/tu_darmstadt/informatik/tk/scopviz/ui/ButtonManager.java

@@ -1,5 +1,8 @@
 package de.tu_darmstadt.informatik.tk.scopviz.ui;
 package de.tu_darmstadt.informatik.tk.scopviz.ui;
 
 
+import java.awt.Event;
+import java.io.IOException;
+import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.ArrayList;
 
 
 import org.graphstream.graph.implementations.Graphs;
 import org.graphstream.graph.implementations.Graphs;
@@ -15,8 +18,12 @@ import de.tu_darmstadt.informatik.tk.scopviz.ui.mapView.MapViewFunctions;
 import de.tu_darmstadt.informatik.tk.scopviz.ui.mapView.WorldView;
 import de.tu_darmstadt.informatik.tk.scopviz.ui.mapView.WorldView;
 import javafx.beans.value.ObservableValue;
 import javafx.beans.value.ObservableValue;
 import javafx.event.ActionEvent;
 import javafx.event.ActionEvent;
+import javafx.scene.control.Alert;
+import javafx.scene.control.Alert.AlertType;
 import javafx.scene.control.Button;
 import javafx.scene.control.Button;
 import javafx.scene.control.TableRow;
 import javafx.scene.control.TableRow;
+import javafx.scene.input.MouseButton;
+import javafx.scene.input.MouseEvent;
 
 
 /**
 /**
  * Manager to contain the various handlers for the buttons of the UI.
  * Manager to contain the various handlers for the buttons of the UI.
@@ -182,8 +189,22 @@ public final class ButtonManager {
 			GraphDisplayManager.setCurrentLayer(Layer.SYMBOL);
 			GraphDisplayManager.setCurrentLayer(Layer.SYMBOL);
 			GraphDisplayManager.addGraph(gClone, true);
 			GraphDisplayManager.addGraph(gClone, true);
 
 
+		}
+		
+		try {
+			// load world view 
 			activateWorldView();
 			activateWorldView();
-
+			
+		} catch (IOException e) {
+			
+			// problems with Internet connection, maybe host not reachable, maybe no Internet connection at all
+			GraphDisplayManager.switchActiveGraph();
+			setBorderStyle((Button) arg0.getSource());
+			
+			// show "Connection Error" message
+			showConnectionErrorMsg();
+			
+			return;
 		}
 		}
 
 
 		GraphDisplayManager.switchActiveGraph();
 		GraphDisplayManager.switchActiveGraph();
@@ -192,10 +213,23 @@ public final class ButtonManager {
 		controller.getOpenButton().setText("Open...");
 		controller.getOpenButton().setText("Open...");
 	}
 	}
 
 
+	/**
+	 * show an Alert dialog when OpenStreetMap could not be loaded
+	 */
+	public static void showConnectionErrorMsg() {
+		Alert alert = new Alert(AlertType.WARNING);
+		alert.setTitle("Connection Error");
+		alert.setHeaderText("Could not reach OpenStreetMap server");
+		alert.setContentText(null);
+
+		alert.showAndWait();
+	}
+
 	/**
 	/**
 	 * Initializes the WorldView, sets data and paints them.
 	 * Initializes the WorldView, sets data and paints them.
+	 * @throws IOException 
 	 */
 	 */
-	private static void activateWorldView() {
+	private static void activateWorldView() throws IOException {
 
 
 		// dont show graph and toolbox
 		// dont show graph and toolbox
 		controller.toolbox.setVisible(false);
 		controller.toolbox.setVisible(false);

+ 7 - 4
scopviz/src/main/java/de/tu_darmstadt/informatik/tk/scopviz/ui/mapView/CustomMapClickListener.java

@@ -9,7 +9,6 @@ import org.jxmapviewer.JXMapViewer;
 import org.jxmapviewer.input.MapClickListener;
 import org.jxmapviewer.input.MapClickListener;
 import org.jxmapviewer.viewer.GeoPosition;
 import org.jxmapviewer.viewer.GeoPosition;
 
 
-import de.tu_darmstadt.informatik.tk.scopviz.debug.Debug;
 import de.tu_darmstadt.informatik.tk.scopviz.main.Layer;
 import de.tu_darmstadt.informatik.tk.scopviz.main.Layer;
 import de.tu_darmstadt.informatik.tk.scopviz.ui.GraphDisplayManager;
 import de.tu_darmstadt.informatik.tk.scopviz.ui.GraphDisplayManager;
 import de.tu_darmstadt.informatik.tk.scopviz.ui.PropertiesManager;
 import de.tu_darmstadt.informatik.tk.scopviz.ui.PropertiesManager;
@@ -30,13 +29,17 @@ public class CustomMapClickListener extends MapClickListener {
 	 * all edges of the graph
 	 * all edges of the graph
 	 */
 	 */
 	private final static HashSet<Edge> edges = WorldView.edges;
 	private final static HashSet<Edge> edges = WorldView.edges;
-	
+
 	/*
 	/*
 	 * all waypoints of the graph
 	 * all waypoints of the graph
 	 */
 	 */
 	private final static HashSet<CustomWaypoint> waypoints = WorldView.waypoints;
 	private final static HashSet<CustomWaypoint> waypoints = WorldView.waypoints;
-	
 
 
+	/**
+	 * Constructor sets viewer
+	 * 
+	 * @param viewer
+	 */
 	public CustomMapClickListener(JXMapViewer viewer) {
 	public CustomMapClickListener(JXMapViewer viewer) {
 		super(viewer);
 		super(viewer);
 
 
@@ -124,7 +127,7 @@ public class CustomMapClickListener extends MapClickListener {
 	 * deselect all edges and the selected node
 	 * deselect all edges and the selected node
 	 */
 	 */
 	public static void deselectAll() {
 	public static void deselectAll() {
-		if (selected != null){
+		if (selected != null) {
 			selected.deselect();
 			selected.deselect();
 			selected = null;
 			selected = null;
 		}
 		}

+ 163 - 0
scopviz/src/main/java/de/tu_darmstadt/informatik/tk/scopviz/ui/mapView/CustomTile.java

@@ -0,0 +1,163 @@
+package de.tu_darmstadt.informatik.tk.scopviz.ui.mapView;
+
+import java.awt.image.BufferedImage;
+import java.lang.ref.SoftReference;
+
+import org.jxmapviewer.viewer.Tile;
+
+/**
+ * The Tile class represents a particular square image piece of the world bitmap
+ * at a particular zoom level.
+ * 
+ * @author joshy
+ */
+
+public class CustomTile extends Tile {
+
+	/**
+	 * Indicates that loading has succeeded. A PropertyChangeEvent will be fired
+	 * when the loading is completed
+	 */
+
+	private boolean loaded = false;
+
+	private Priority priority = Priority.High;
+
+	private CustomTileFactory dtf;
+
+	private boolean isLoading = false;
+
+	/**
+	 * The url of the image to load for this tile
+	 */
+	private String url;
+
+	/**
+	 * The image loaded for this Tile
+	 */
+	SoftReference<BufferedImage> image = new SoftReference<BufferedImage>(null);
+
+	/**
+	 * Create a new Tile at the specified tile point and zoom level
+	 * 
+	 * @param x
+	 *            the x value
+	 * @param y
+	 *            the y value
+	 * @param zoom
+	 *            the zoom level
+	 */
+	public CustomTile(int x, int y, int zoom) {
+		super(x, y, zoom);
+	}
+
+	/**
+	 * Create a new Tile that loads its data from the given URL. The URL must
+	 * resolve to an image
+	 * 
+	 * @param x
+	 *            the x value
+	 * @param y
+	 *            the y value
+	 * @param zoom
+	 *            the zoom level
+	 * @param url
+	 *            the URL
+	 * @param priority
+	 *            the priority
+	 * @param dtf
+	 *            the tile factory
+	 */
+	public CustomTile(int x, int y, int zoom, String url, Priority priority, CustomTileFactory dtf) {
+		super(x, y, zoom);
+		this.url = url;
+		this.priority = priority;
+		this.dtf = dtf;
+	}
+
+	/**
+	 * @return the Image associated with this Tile. This is a read only property
+	 *         This may return null at any time, however if this returns null, a
+	 *         load operation will automatically be started for it.
+	 */
+	public BufferedImage getImage() {
+		BufferedImage img = image.get();
+		if (img == null) {
+			setLoaded(false);
+
+			// tile factory can be null if the tile has invalid coords or zoom
+			if (dtf != null) {
+				dtf.startLoading(this);
+			}
+		}
+
+		return img;
+	}
+
+	/**
+	 * Indicates if this tile's underlying image has been successfully loaded
+	 * yet.
+	 * 
+	 * @return true if the Tile has been loaded
+	 */
+	public synchronized boolean isLoaded() {
+		return loaded;
+	}
+
+	/**
+	 * Toggles the loaded state, and fires the appropriate property change
+	 * notification
+	 * 
+	 * @param loaded
+	 *            the loaded flag
+	 */
+	public synchronized void setLoaded(boolean loaded) {
+		boolean old = isLoaded();
+		this.loaded = loaded;
+		firePropertyChange("loaded", old, isLoaded());
+	}
+
+	/**
+	 * @return the isLoading
+	 */
+	public boolean isLoading() {
+		return isLoading;
+	}
+
+	/**
+	 * @param isLoading
+	 *            the isLoading to set
+	 */
+	public void setLoading(boolean isLoading) {
+		this.isLoading = isLoading;
+	}
+
+	/**
+	 * Gets the loading priority of this tile.
+	 * 
+	 * @return the priority
+	 */
+	public Priority getPriority() {
+		return priority;
+	}
+
+	/**
+	 * Set the loading priority of this tile.
+	 * 
+	 * @param priority
+	 *            the priority to set
+	 */
+	public void setPriority(Priority priority) {
+		this.priority = priority;
+	}
+
+	/**
+	 * Gets the URL of this tile.
+	 * 
+	 * @return the url
+	 */
+	public String getURL() {
+		return url;
+	}
+
+}

+ 365 - 0
scopviz/src/main/java/de/tu_darmstadt/informatik/tk/scopviz/ui/mapView/CustomTileFactory.java

@@ -0,0 +1,365 @@
+package de.tu_darmstadt.informatik.tk.scopviz.ui.mapView;
+
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.ref.SoftReference;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.net.URLConnection;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.PriorityBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+
+import javax.imageio.ImageIO;
+import javax.swing.SwingUtilities;
+
+import org.jxmapviewer.util.ProjectProperties;
+import org.jxmapviewer.viewer.AbstractTileFactory;
+import org.jxmapviewer.viewer.Tile;
+import org.jxmapviewer.viewer.TileCache;
+import org.jxmapviewer.viewer.TileFactoryInfo;
+import org.jxmapviewer.viewer.util.GeoUtil;
+
+public class CustomTileFactory extends AbstractTileFactory {
+
+	/**
+	 * Note that the name and version are actually set by Gradle so there is no
+	 * need to bump a version manually when new release is made.
+	 */
+	private static final String DEFAULT_USER_AGENT = ProjectProperties.INSTANCE.getName() + "/"
+			+ ProjectProperties.INSTANCE.getVersion();
+
+	private String userAgent = DEFAULT_USER_AGENT;
+
+	private int threadPoolSize = 4;
+	private ExecutorService service;
+
+	// TODO the tile map should be static ALWAYS, regardless of the number
+	// of GoogleTileFactories because each tile is, really, a singleton.
+	private Map<String, Tile> tileMap = new HashMap<String, Tile>();
+
+	private TileCache cache = new TileCache();
+
+	public CustomTileFactory(TileFactoryInfo info) {
+		super(info);
+	}
+
+	/**
+	 * Returns the tile that is located at the given tilePoint for this zoom.
+	 * For example, if getMapSize() returns 10x20 for this zoom, and the
+	 * tilePoint is (3,5), then the appropriate tile will be located and
+	 * returned.
+	 */
+	@Override
+	public CustomTile getTile(int x, int y, int zoom) {
+		return (CustomTile) getTile(x, y, zoom, true);
+	}
+
+	private CustomTile getTile(int tpx, int tpy, int zoom, boolean eagerLoad) {
+		// wrap the tiles horizontally --> mod the X with the max width
+		// and use that
+		int tileX = tpx;// tilePoint.getX();
+		int numTilesWide = (int) getMapSize(zoom).getWidth();
+		if (tileX < 0) {
+			tileX = numTilesWide - (Math.abs(tileX) % numTilesWide);
+		}
+
+		tileX = tileX % numTilesWide;
+		int tileY = tpy;
+		// TilePoint tilePoint = new TilePoint(tileX, tpy);
+		String url = getInfo().getTileUrl(tileX, tileY, zoom);// tilePoint);
+		// System.out.println("loading: " + url);
+
+		Tile.Priority pri = Tile.Priority.High;
+		if (!eagerLoad) {
+			pri = Tile.Priority.Low;
+		}
+		CustomTile tile;
+		// System.out.println("testing for validity: " + tilePoint + " zoom = "
+		// + zoom);
+		if (!tileMap.containsKey(url)) {
+			if (!GeoUtil.isValidTile(tileX, tileY, zoom, getInfo())) {
+				tile = new CustomTile(tileX, tileY, zoom);
+			} else {
+				tile = new CustomTile(tileX, tileY, zoom, url, pri, this);
+				startLoading(tile);
+			}
+			tileMap.put(url, tile);
+		} else {
+			tile = (CustomTile) tileMap.get(url);
+			// if its in the map but is low and isn't loaded yet
+			// but we are in high mode
+			if (tile.getPriority() == Tile.Priority.Low && eagerLoad && !tile.isLoaded()) {
+				// System.out.println("in high mode and want a low");
+				// tile.promote();
+				promote(tile);
+			}
+		}
+
+		/*
+		 * if (eagerLoad && doEagerLoading) { for (int i = 0; i<1; i++) { for
+		 * (int j = 0; j<1; j++) { // preload the 4 tiles under the current one
+		 * if(zoom > 0) { eagerlyLoad(tilePoint.getX()*2, tilePoint.getY()*2,
+		 * zoom-1); eagerlyLoad(tilePoint.getX()*2+1, tilePoint.getY()*2,
+		 * zoom-1); eagerlyLoad(tilePoint.getX()*2, tilePoint.getY()*2+1,
+		 * zoom-1); eagerlyLoad(tilePoint.getX()*2+1, tilePoint.getY()*2+1,
+		 * zoom-1); } } } }
+		 */
+
+		return tile;
+	}
+
+	/** ==== threaded tile loading stuff === */
+	/**
+	 * Thread pool for loading the tiles
+	 */
+	private BlockingQueue<Tile> tileQueue = new PriorityBlockingQueue<Tile>(5, new Comparator<Tile>() {
+		@Override
+		public int compare(Tile o1, Tile o2) {
+			if (o1.getPriority() == Tile.Priority.Low && o2.getPriority() == Tile.Priority.High) {
+				return 1;
+			}
+			if (o1.getPriority() == Tile.Priority.High && o2.getPriority() == Tile.Priority.Low) {
+				return -1;
+			}
+			return 0;
+
+		}
+	});
+
+	/**
+	 * @return the tile cache
+	 */
+	public TileCache getTileCache() {
+		return cache;
+	}
+
+	/**
+	 * @param cache
+	 *            the tile cache
+	 */
+	public void setTileCache(TileCache cache) {
+		this.cache = cache;
+	}
+
+	/**
+	 * Subclasses may override this method to provide their own executor
+	 * services. This method will be called each time a tile needs to be loaded.
+	 * Implementations should cache the ExecutorService when possible.
+	 * 
+	 * @return ExecutorService to load tiles with
+	 */
+	protected synchronized ExecutorService getService() {
+		if (service == null) {
+			// System.out.println("creating an executor service with a
+			// threadpool of size " + threadPoolSize);
+			service = Executors.newFixedThreadPool(threadPoolSize, new ThreadFactory() {
+				private int count = 0;
+
+				@Override
+				public Thread newThread(Runnable r) {
+					Thread t = new Thread(r, "tile-pool-" + count++);
+					t.setPriority(Thread.MIN_PRIORITY);
+					t.setDaemon(true);
+					return t;
+				}
+			});
+		}
+		return service;
+	}
+
+	@Override
+	public void dispose() {
+		if (service != null) {
+			service.shutdown();
+			service = null;
+		}
+	}
+
+	/**
+	 * Set the number of threads to use for loading the tiles. This controls the
+	 * number of threads used by the ExecutorService returned from getService().
+	 * Note, this method should be called before loading the first tile. Calls
+	 * after the first tile are loaded will have no effect by default.
+	 * 
+	 * @param size
+	 *            the thread pool size
+	 */
+	public void setThreadPoolSize(int size) {
+		if (size <= 0) {
+			throw new IllegalArgumentException(
+					"size invalid: " + size + ". The size of the threadpool must be greater than 0.");
+		}
+		threadPoolSize = size;
+	}
+
+	@Override
+	protected synchronized void startLoading(Tile tile) {
+		if (tile.isLoading()) {
+			// System.out.println("already loading. bailing");
+			return;
+		}
+		tile.setLoading(true);
+		try {
+			tileQueue.put(tile);
+			getService().submit(createTileRunner(tile));
+		} catch (Exception ex) {
+			ex.printStackTrace();
+		}
+	}
+
+	/**
+	 * Increase the priority of this tile so it will be loaded sooner.
+	 * 
+	 * @param tile
+	 *            the tile
+	 */
+	public synchronized void promote(CustomTile tile) {
+		if (tileQueue.contains(tile)) {
+			try {
+				tileQueue.remove(tile);
+				tile.setPriority(Tile.Priority.High);
+				tileQueue.put(tile);
+			} catch (Exception ex) {
+				ex.printStackTrace();
+			}
+		}
+	}
+
+	@Override
+	protected Runnable createTileRunner(Tile tile) {
+		return new CustomTileRunner();
+	}
+
+	/**
+	 * An inner class which actually loads the tiles. Used by the thread queue.
+	 * Subclasses can override this if necessary.
+	 */
+	private class CustomTileRunner implements Runnable {
+		/**
+		 * Gets the full URI of a tile.
+		 * 
+		 * @param tile
+		 *            the tile
+		 * @throws URISyntaxException
+		 *             if the URI is invalid
+		 * @return a URI for the tile
+		 */
+		protected URI getURI(Tile tile) throws URISyntaxException {
+			if (tile.getURL() == null) {
+				return null;
+			}
+			return new URI(tile.getURL());
+		}
+
+		/**
+		 * implementation of the Runnable interface.
+		 */
+		@Override
+		public void run() {
+			/*
+			 * 3 strikes and you're out. Attempt to load the url. If it fails,
+			 * decrement the number of tries left and try again. Log failures.
+			 * If I run out of try s just get out. This way, if there is some
+			 * kind of serious failure, I can get out and let other tiles try to
+			 * load.
+			 */
+			final CustomTile tile = (CustomTile) tileQueue.remove();
+
+			int trys = 3;
+			while (!tile.isLoaded() && trys > 0) {
+				try {
+					BufferedImage img;
+					URI uri = getURI(tile);
+					img = cache.get(uri);
+					if (img == null) {
+						byte[] bimg = cacheInputStream(uri.toURL());
+						img = ImageIO.read(new ByteArrayInputStream(bimg));
+						cache.put(uri, bimg, img);
+						img = cache.get(uri);
+					}
+					if (img != null) {
+
+						final BufferedImage i = img;
+						SwingUtilities.invokeAndWait(new Runnable() {
+							@Override
+							public void run() {
+								tile.image = new SoftReference<BufferedImage>(i);
+								tile.setLoaded(true);
+								fireTileLoadedEvent(tile);
+							}
+						});
+					} else {
+						trys--;
+					}
+
+				} catch (OutOfMemoryError memErr) {
+					// Cache out of memory
+					cache.needMoreMemory();
+
+				} catch (Throwable e) {
+					// tile could not be loaded
+					if (trys == 0) {
+						URL url;
+						BufferedImage img;
+
+						try {
+							// try and load standard tile png
+							url = CustomTileFactory.class.getResource("/images/loading.png");
+							img = ImageIO.read(url);
+
+						} catch (Exception ex) {
+							// standard png could not be loaded, so make one on
+							// your own
+							img = new BufferedImage(16, 16, BufferedImage.TYPE_INT_ARGB);
+							Graphics2D g2 = img.createGraphics();
+							g2.setColor(Color.black);
+							g2.fillRect(0, 0, 16, 16);
+							g2.dispose();
+						}
+
+						// set tile image
+						tile.image = new SoftReference<BufferedImage>(img);
+
+					} else {
+						trys--;
+					}
+				}
+
+			}
+			tile.setLoading(false);
+		}
+
+		private byte[] cacheInputStream(URL url) throws IOException {
+			URLConnection connection = url.openConnection();
+			connection.setRequestProperty("User-Agent", userAgent);
+			InputStream ins = connection.getInputStream();
+
+			ByteArrayOutputStream bout = new ByteArrayOutputStream();
+			byte[] buf = new byte[256];
+			while (true) {
+				int n = ins.read(buf);
+				if (n == -1)
+					break;
+				bout.write(buf, 0, n);
+			}
+			ins.close();
+
+			byte[] data = bout.toByteArray();
+			bout.close();
+			return data;
+		}
+	}
+
+}

+ 3 - 3
scopviz/src/main/java/de/tu_darmstadt/informatik/tk/scopviz/ui/mapView/CustomWaypoint.java

@@ -22,7 +22,7 @@ public class CustomWaypoint extends DefaultWaypoint {
 	/**
 	/**
 	 * @param label
 	 * @param label
 	 *            the text
 	 *            the text
-	 * @param deviceType 
+	 * @param deviceType
 	 * @param color
 	 * @param color
 	 *            the color
 	 *            the color
 	 * @param coord
 	 * @param coord
@@ -57,10 +57,10 @@ public class CustomWaypoint extends DefaultWaypoint {
 	public String getNodeID() {
 	public String getNodeID() {
 		return nodeID;
 		return nodeID;
 	}
 	}
-	
+
 	/**
 	/**
 	 * 
 	 * 
-	 * @return the device type 
+	 * @return the device type
 	 */
 	 */
 	public String getDeviceType() {
 	public String getDeviceType() {
 		return deviceType;
 		return deviceType;

+ 6 - 7
scopviz/src/main/java/de/tu_darmstadt/informatik/tk/scopviz/ui/mapView/CustomWaypointRenderer.java

@@ -8,8 +8,6 @@ import java.awt.RenderingHints;
 import java.awt.geom.Point2D;
 import java.awt.geom.Point2D;
 import java.awt.image.BufferedImage;
 import java.awt.image.BufferedImage;
 
 
-import javax.imageio.ImageIO;
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.logging.LogFactory;
 import org.jxmapviewer.JXMapViewer;
 import org.jxmapviewer.JXMapViewer;
@@ -28,23 +26,24 @@ public class CustomWaypointRenderer implements WaypointRenderer<CustomWaypoint>
 	public static final Color CLICKED = Color.RED;
 	public static final Color CLICKED = Color.RED;
 
 
 	public static final int ALPHA = 255;
 	public static final int ALPHA = 255;
-	
+
 	public static final int SCALEWIDTH = 60;
 	public static final int SCALEWIDTH = 60;
-	
+
 	public static final int SCALEHEIGHT = 60;
 	public static final int SCALEHEIGHT = 60;
 
 
 	@Override
 	@Override
 	public void paintWaypoint(Graphics2D g, JXMapViewer viewer, CustomWaypoint w) {
 	public void paintWaypoint(Graphics2D g, JXMapViewer viewer, CustomWaypoint w) {
 
 
 		g = (Graphics2D) g.create();
 		g = (Graphics2D) g.create();
-	
+
 		// get pre loaded image
 		// get pre loaded image
 		BufferedImage loadedImg = MapViewFunctions.imageMap.get(w.getDeviceType());
 		BufferedImage loadedImg = MapViewFunctions.imageMap.get(w.getDeviceType());
 
 
 		if (w.getIsSelected()) {
 		if (w.getIsSelected()) {
-			loadedImg = MapViewFunctions.colorImage(loadedImg, CustomWaypointRenderer.STANDARD, CustomWaypointRenderer.CLICKED, CustomWaypointRenderer.ALPHA);
+			loadedImg = MapViewFunctions.colorImage(loadedImg, CustomWaypointRenderer.STANDARD,
+					CustomWaypointRenderer.CLICKED, CustomWaypointRenderer.ALPHA);
 		}
 		}
-		
+
 		// get waypoint position
 		// get waypoint position
 		Point2D point = viewer.getTileFactory().geoToPixel(w.getPosition(), viewer.getZoom());
 		Point2D point = viewer.getTileFactory().geoToPixel(w.getPosition(), viewer.getZoom());
 
 

+ 26 - 24
scopviz/src/main/java/de/tu_darmstadt/informatik/tk/scopviz/ui/mapView/MapViewFunctions.java

@@ -22,7 +22,6 @@ import org.jxmapviewer.viewer.GeoPosition;
 import org.jxmapviewer.viewer.TileFactoryInfo;
 import org.jxmapviewer.viewer.TileFactoryInfo;
 import org.jxmapviewer.viewer.WaypointPainter;
 import org.jxmapviewer.viewer.WaypointPainter;
 
 
-import de.tu_darmstadt.informatik.tk.scopviz.debug.Debug;
 import de.tu_darmstadt.informatik.tk.scopviz.graphs.GraphManager;
 import de.tu_darmstadt.informatik.tk.scopviz.graphs.GraphManager;
 import de.tu_darmstadt.informatik.tk.scopviz.main.Layer;
 import de.tu_darmstadt.informatik.tk.scopviz.main.Layer;
 import de.tu_darmstadt.informatik.tk.scopviz.main.MainApp;
 import de.tu_darmstadt.informatik.tk.scopviz.main.MainApp;
@@ -32,54 +31,56 @@ import de.tu_darmstadt.informatik.tk.scopviz.ui.PropertiesManager;
 public final class MapViewFunctions {
 public final class MapViewFunctions {
 
 
 	private static final Log log = LogFactory.getLog(MapViewFunctions.class);
 	private static final Log log = LogFactory.getLog(MapViewFunctions.class);
-	
+
 	// Hash map to save, scaled images
 	// Hash map to save, scaled images
-	public static HashMap<String, BufferedImage> imageMap = new HashMap<String, BufferedImage>(WorldView.waypoints.size());
-	
+	public static HashMap<String, BufferedImage> imageMap = new HashMap<String, BufferedImage>(
+			WorldView.waypoints.size());
+
 	/**
 	/**
 	 * private constructor to avoid instantiation
 	 * private constructor to avoid instantiation
 	 */
 	 */
 	private MapViewFunctions() {
 	private MapViewFunctions() {
 
 
 	}
 	}
-	
+
 	/**
 	/**
 	 * resets the hash map with the pictures
 	 * resets the hash map with the pictures
 	 */
 	 */
-	public static void resetImageMap(){
+	public static void resetImageMap() {
 		imageMap = new HashMap<String, BufferedImage>(WorldView.waypoints.size());
 		imageMap = new HashMap<String, BufferedImage>(WorldView.waypoints.size());
 	}
 	}
-	
+
 	/**
 	/**
 	 * load and scale waypoint images and save them in a HashMap
 	 * load and scale waypoint images and save them in a HashMap
 	 */
 	 */
-	public static void initializeWaypointImages(){
-		
-		for(CustomWaypoint w : WorldView.waypoints){
-		
+	public static void initializeWaypointImages() {
+
+		for (CustomWaypoint w : WorldView.waypoints) {
+
 			BufferedImage origImage = null;
 			BufferedImage origImage = null;
 
 
 			// image not loaded
 			// image not loaded
-			if(!imageMap.containsKey(w.getDeviceType())){
-				
+			if (!imageMap.containsKey(w.getDeviceType())) {
+
 				// try load image
 				// try load image
 				try {
 				try {
 					origImage = ImageIO.read(w.getResource());
 					origImage = ImageIO.read(w.getResource());
-					
+
 				} catch (Exception ex) {
 				} catch (Exception ex) {
 					log.warn("couldn't read Waypoint png", ex);
 					log.warn("couldn't read Waypoint png", ex);
 				}
 				}
-				
+
 				// loading complete
 				// loading complete
-				if (origImage != null) {	
+				if (origImage != null) {
 					// scale image down
 					// scale image down
-					BufferedImage myImg = MapViewFunctions.scaleImage(origImage, CustomWaypointRenderer.SCALEWIDTH, CustomWaypointRenderer.SCALEHEIGHT);
-					
+					BufferedImage myImg = MapViewFunctions.scaleImage(origImage, CustomWaypointRenderer.SCALEWIDTH,
+							CustomWaypointRenderer.SCALEHEIGHT);
+
 					// save image in hash map
 					// save image in hash map
 					imageMap.put(w.getDeviceType(), myImg);
 					imageMap.put(w.getDeviceType(), myImg);
 				}
 				}
 			}
 			}
-			
+
 		}
 		}
 
 
 	}
 	}
@@ -117,7 +118,7 @@ public final class MapViewFunctions {
 	public static BufferedImage colorImage(BufferedImage image, Color toChange, Color changeWith, int alpha) {
 	public static BufferedImage colorImage(BufferedImage image, Color toChange, Color changeWith, int alpha) {
 		int width = image.getWidth();
 		int width = image.getWidth();
 		int height = image.getHeight();
 		int height = image.getHeight();
-		
+
 		BufferedImage imgOut = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
 		BufferedImage imgOut = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
 
 
 		for (int xx = 0; xx < width; xx++) {
 		for (int xx = 0; xx < width; xx++) {
@@ -169,17 +170,18 @@ public final class MapViewFunctions {
 				URL resource = getDeviceTypeURL(deviceType);
 				URL resource = getDeviceTypeURL(deviceType);
 
 
 				// create a new waypoint with the node information
 				// create a new waypoint with the node information
-				waypoints.add(new CustomWaypoint(node.getAttribute("ui.label"), node.getId(), resource, deviceType, geoPos));
+				waypoints.add(
+						new CustomWaypoint(node.getAttribute("ui.label"), node.getId(), resource, deviceType, geoPos));
 
 
 			}
 			}
 		}
 		}
-		
+
 		// deselect all previously clicked waypoints or edges
 		// deselect all previously clicked waypoints or edges
 		PropertiesManager.showNewDataSet(null);
 		PropertiesManager.showNewDataSet(null);
-		
+
 		// load and save waypoint images
 		// load and save waypoint images
 		MapViewFunctions.initializeWaypointImages();
 		MapViewFunctions.initializeWaypointImages();
-		
+
 	}
 	}
 
 
 	/**
 	/**

+ 31 - 6
scopviz/src/main/java/de/tu_darmstadt/informatik/tk/scopviz/ui/mapView/WorldView.java

@@ -1,5 +1,9 @@
 package de.tu_darmstadt.informatik.tk.scopviz.ui.mapView;
 package de.tu_darmstadt.informatik.tk.scopviz.ui.mapView;
 
 
+import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLConnection;
 import java.util.ArrayList;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.HashSet;
 import java.util.List;
 import java.util.List;
@@ -9,7 +13,6 @@ import org.jxmapviewer.JXMapViewer;
 import org.jxmapviewer.OSMTileFactoryInfo;
 import org.jxmapviewer.OSMTileFactoryInfo;
 import org.jxmapviewer.painter.CompoundPainter;
 import org.jxmapviewer.painter.CompoundPainter;
 import org.jxmapviewer.painter.Painter;
 import org.jxmapviewer.painter.Painter;
-import org.jxmapviewer.viewer.DefaultTileFactory;
 import org.jxmapviewer.viewer.GeoPosition;
 import org.jxmapviewer.viewer.GeoPosition;
 import org.jxmapviewer.viewer.TileFactoryInfo;
 import org.jxmapviewer.viewer.TileFactoryInfo;
 import org.jxmapviewer.viewer.WaypointPainter;
 import org.jxmapviewer.viewer.WaypointPainter;
@@ -37,7 +40,7 @@ public class WorldView {
 	 * GUIController with UI elements
 	 * GUIController with UI elements
 	 */
 	 */
 	public static GUIController controller;
 	public static GUIController controller;
-	
+
 	/*
 	/*
 	 * All waypoints in the WorldView
 	 * All waypoints in the WorldView
 	 */
 	 */
@@ -47,7 +50,9 @@ public class WorldView {
 	 * All edges in the WorldView
 	 * All edges in the WorldView
 	 */
 	 */
 	public static HashSet<Edge> edges;
 	public static HashSet<Edge> edges;
-	
+
+	public static Thread threadBeforeMapViewLoaded;
+
 	/**
 	/**
 	 * private constructor to avoid instantiation
 	 * private constructor to avoid instantiation
 	 */
 	 */
@@ -67,8 +72,12 @@ public class WorldView {
 
 
 	/**
 	/**
 	 * load map elements based on current underlay graph
 	 * load map elements based on current underlay graph
+	 * 
+	 * @throws IOException
 	 */
 	 */
-	public static void loadWorldView() {
+	public static void loadWorldView() throws IOException {
+
+		threadBeforeMapViewLoaded = Thread.currentThread();
 
 
 		HashSet<GeoPosition> nodePositions = new HashSet<GeoPosition>();
 		HashSet<GeoPosition> nodePositions = new HashSet<GeoPosition>();
 		waypoints = new HashSet<CustomWaypoint>();
 		waypoints = new HashSet<CustomWaypoint>();
@@ -94,7 +103,23 @@ public class WorldView {
 
 
 		// Create a TileFactoryInfo for OpenStreetMap
 		// Create a TileFactoryInfo for OpenStreetMap
 		TileFactoryInfo info = new OSMTileFactoryInfo();
 		TileFactoryInfo info = new OSMTileFactoryInfo();
-		DefaultTileFactory tileFactory = new DefaultTileFactory(info);
+
+		// try to load OpenStreesMap, when errors occur, throw and handle
+		// Exceptions
+		URL osmWebPage;
+		try {
+			// try to connect to OpenStreetMap server
+			osmWebPage = new URL(info.getBaseURL());
+			URLConnection connection = osmWebPage.openConnection();
+			connection.connect();
+
+		} catch (MalformedURLException e) {
+			// TODO add Dialog with eroor msg and stack trace
+			e.printStackTrace();
+
+		}
+
+		CustomTileFactory tileFactory = new CustomTileFactory(info);
 		internMapViewer.setTileFactory(tileFactory);
 		internMapViewer.setTileFactory(tileFactory);
 
 
 		// Use 8 threads in parallel to load the tiles
 		// Use 8 threads in parallel to load the tiles
@@ -107,7 +132,7 @@ public class WorldView {
 
 
 		// "click on waypoints" listener
 		// "click on waypoints" listener
 		internMapViewer.addMouseListener(new CustomMapClickListener(internMapViewer));
 		internMapViewer.addMouseListener(new CustomMapClickListener(internMapViewer));
-		
+
 		internMapViewer.repaint();
 		internMapViewer.repaint();
 	}
 	}