aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHallvard Traetteberg2012-04-09 15:30:54 (EDT)
committerHallvard Traetteberg2012-04-09 15:30:54 (EDT)
commit3637783b355d5be3b3204e73e0b7970ad1e88cf3 (patch)
tree83de3c0b442211626281b4101e2ce94d2007b25f
parentd684e46cee15148bc8cebf56013001ed0ffec75e (diff)
downloadorg.eclipse.nebula-3637783b355d5be3b3204e73e0b7970ad1e88cf3.zip
org.eclipse.nebula-3637783b355d5be3b3204e73e0b7970ad1e88cf3.tar.gz
org.eclipse.nebula-3637783b355d5be3b3204e73e0b7970ad1e88cf3.tar.bz2
Initial commit
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/.classpath7
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/.project28
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/META-INF/MANIFEST.MF11
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/about.html28
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/build.properties5
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/plugin.properties2
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/pom.xml17
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/DefaultMouseHandler.java113
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/GeoMapViewer.java318
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/GoogleIconDescriptor.java146
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/IPinPointProvider.java31
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/LocationProvider.java32
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/MouseHandler.java100
-rw-r--r--widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/PinPointProvider.java61
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/.cvsignore1
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/.project17
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/build.properties1
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/feature.xml51
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/pom.xml18
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.classpath7
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.cvsignore1
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.project28
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.settings/org.eclipse.jdt.core.prefs7
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/META-INF/MANIFEST.MF12
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/about.html28
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/build.properties4
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/plugin.properties2
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/pom.xml17
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/src/org/eclipse/nebula/widgets/geomap/snippets/GeoMapBrowserSnippet01.java39
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/src/org/eclipse/nebula/widgets/geomap/snippets/GeoMapSnippet01.java39
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/.classpath7
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/.project28
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.jdt.core.prefs350
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.jdt.ui.prefs106
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.ltk.core.refactoring.prefs3
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.mylyn.tasks.ui.prefs4
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.pde.prefs15
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.wst.validation.prefs6
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/META-INF/MANIFEST.MF10
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/about.html28
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/build.properties16
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/plugin.properties2
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/pom.xml17
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/GeoMap.java714
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/GeoMapBrowser.java119
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/PointD.java38
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/AbstractPage.java132
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/HeaderControl.java113
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/InfoPage.java136
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/Page.java23
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/PageContainer.java98
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/ResultsPage.java155
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/SearchPage.java329
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/TitleControl.java128
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/resources/action.gifbin0 -> 216 bytes
-rw-r--r--widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/resources/world.pngbin0 -> 15230 bytes
57 files changed, 3755 insertions, 0 deletions
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/.classpath b/widgets/geomap/org.eclipse.nebula.jface.geomap/.classpath
new file mode 100644
index 0000000..64c5e31
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/.project b/widgets/geomap/org.eclipse.nebula.jface.geomap/.project
new file mode 100644
index 0000000..5d4cec1
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.nebula.jface.geomap</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/.settings/org.eclipse.jdt.core.prefs b/widgets/geomap/org.eclipse.nebula.jface.geomap/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..6a3f6d4
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+#Sun Feb 22 16:15:51 MST 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/META-INF/MANIFEST.MF b/widgets/geomap/org.eclipse.nebula.jface.geomap/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..c1479fc
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/META-INF/MANIFEST.MF
@@ -0,0 +1,11 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.nebula.jface.geomap
+Bundle-Version: 0.1.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Require-Bundle: org.eclipse.nebula.widgets.geomap;bundle-version="0.1.0",
+ org.eclipse.jface;bundle-version="3.4.0"
+Export-Package: org.eclipse.nebula.jface.geomap
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/about.html b/widgets/geomap/org.eclipse.nebula.jface.geomap/about.html
new file mode 100644
index 0000000..c258ef5
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/build.properties b/widgets/geomap/org.eclipse.nebula.jface.geomap/build.properties
new file mode 100644
index 0000000..aa1a008
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/build.properties
@@ -0,0 +1,5 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/plugin.properties b/widgets/geomap/org.eclipse.nebula.jface.geomap/plugin.properties
new file mode 100644
index 0000000..9a19f52
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/plugin.properties
@@ -0,0 +1,2 @@
+pluginName = GeoMap JFace Plugin (Incubation)
+providerName = Eclipse.org
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/pom.xml b/widgets/geomap/org.eclipse.nebula.jface.geomap/pom.xml
new file mode 100644
index 0000000..6805258
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>nebula-parent</artifactId>
+ <groupId>org.eclipse.nebula</groupId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../../../releng/org.eclipse.nebula.nebula-parent</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.nebula</groupId>
+ <artifactId>org.eclipse.nebula.jface.geomap</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <packaging>eclipse-plugin</packaging>
+
+</project>
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/DefaultMouseHandler.java b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/DefaultMouseHandler.java
new file mode 100644
index 0000000..0fc74d5
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/DefaultMouseHandler.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Hallvard Trūtteberg.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hallvard Trūtteberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.nebula.jface.geomap;
+
+import org.eclipse.nebula.widgets.geomap.GeoMap;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+
+public class DefaultMouseHandler extends MouseHandler {
+
+ public DefaultMouseHandler(GeoMap geoMap) {
+ super(geoMap);
+ }
+
+ private Point downPosition = null;
+ private boolean isPanning = false, isZooming = false;
+
+ @Override
+ protected boolean handleDown(MouseEvent e) {
+ downPosition = this.geoMap.getMapPosition();
+ if (isPanning = isPanDownEvent(e)) {
+ }
+ if (isZooming = isZoomDownEvent(e)) {
+ }
+ if (isCenterDownEvent(e)) {
+ this.geoMap.setCenterPosition(this.geoMap.getCursorPosition());
+ return true;
+ }
+ return false;
+ }
+
+ private Rectangle zoomRectangle;
+
+ @Override
+ protected boolean handleDrag(MouseEvent e) {
+ // undo the effect of MapWidget's own panning
+ this.geoMap.setMapPosition(downPosition.x, downPosition.y);
+ // do our own panning
+ if (isPanning && downPosition != null) {
+ int tx = downCoords.x - e.x;
+ int ty = downCoords.y - e.y;
+ this.geoMap.setMapPosition(downPosition.x + tx, downPosition.y + ty);
+ return true;
+ }
+ if (isZooming && downCoords != null && dragCoords != null) {
+ int minX = Math.min(downCoords.x, dragCoords.x), minY = Math.min(downCoords.y, dragCoords.y);
+ int maxX = Math.max(downCoords.x, dragCoords.x), maxY = Math.max(downCoords.y, dragCoords.y);
+ Point mapPosition = this.geoMap.getMapPosition();
+ zoomRectangle = new Rectangle(mapPosition.x + minX, mapPosition.y + minY, maxX - minX, maxY - minY);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void paintControl(PaintEvent e) {
+ super.paintControl(e);
+ if (zoomRectangle != null) {
+ Point mapPosition = this.geoMap.getMapPosition();
+ e.gc.drawRectangle(zoomRectangle.x - mapPosition.x, zoomRectangle.y - mapPosition.y, zoomRectangle.width, zoomRectangle.height);
+ }
+ }
+
+ @Override
+ protected boolean handleUp(MouseEvent e) {
+ if (e.count == 1) {
+ handleDrag(e);
+ }
+ if (isZooming && downCoords != null) {
+ Point mapSize = this.geoMap.getSize();
+ int diff = Math.min(mapSize.x / zoomRectangle.width, mapSize.y / zoomRectangle.height);
+ while (diff > 1) {
+ Point mapPosition = this.geoMap.getMapPosition();
+ // pivot on center of zoom rectangle
+ Point pivot = new Point(zoomRectangle.x - mapPosition.x + zoomRectangle.width / 2, zoomRectangle.y - mapPosition.y + zoomRectangle.height / 2);
+ this.geoMap.zoomIn(pivot);
+ // scale zoom rectangle up, to match zoom level
+ zoomRectangle = new Rectangle(zoomRectangle.x * 2, zoomRectangle.y * 2, zoomRectangle.width * 2, zoomRectangle.height * 2);
+ diff /= 2;
+ }
+ }
+ downPosition = null;
+ isPanning = false;
+ isZooming = false;
+ zoomRectangle = null;
+ return true;
+ }
+
+ // can be overridden to provide new functionality
+
+ protected boolean isCenterDownEvent(MouseEvent e) {
+ return e.button == 1 && (e.stateMask & SWT.CTRL) != 0;
+ }
+
+ protected boolean isPanDownEvent(MouseEvent e) {
+ return e.button == 1 && (e.stateMask & SWT.SHIFT) == 0;
+ }
+
+ protected boolean isZoomDownEvent(MouseEvent e) {
+ return e.button == 1 && (e.stateMask & SWT.SHIFT) != 0;
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/GeoMapViewer.java b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/GeoMapViewer.java
new file mode 100644
index 0000000..2c9693b
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/GeoMapViewer.java
@@ -0,0 +1,318 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Hallvard Trūtteberg.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hallvard Trūtteberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.nebula.jface.geomap;
+
+import org.eclipse.jface.viewers.ContentViewer;
+import org.eclipse.jface.viewers.IBaseLabelProvider;
+import org.eclipse.jface.viewers.IContentProvider;
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.jface.viewers.ISelection;
+import org.eclipse.jface.viewers.IStructuredContentProvider;
+import org.eclipse.jface.viewers.IStructuredSelection;
+import org.eclipse.jface.viewers.LabelProviderChangedEvent;
+import org.eclipse.jface.viewers.StructuredSelection;
+import org.eclipse.nebula.widgets.geomap.GeoMap;
+import org.eclipse.nebula.widgets.geomap.PointD;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * A JFace viewer for the GeoMap widget
+ * @author hal
+ *
+ */
+public class GeoMapViewer extends ContentViewer {
+
+ private GeoMap geoMap;
+
+ private LocationProvider locationProvider;
+
+ private Object selection = null;
+ private Point selectionOffset = null;
+
+ private MouseHandler mouseHandler;
+
+ /**
+ * Creates a GeoMapViewer for a specific GeoMap
+ * @param geoMap the GeoMap
+ */
+ public GeoMapViewer(GeoMap geoMap) {
+ this.geoMap = geoMap;
+ setMouseHandler(new MovePinMouseHandler(geoMap));
+ geoMap.addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent e) {
+ paintOverlay(e);
+ }
+ });
+ }
+
+ private void setMouseHandler(MovePinMouseHandler mouseHandler) {
+ if (this.mouseHandler != null) {
+ geoMap.removeMouseListener(this.mouseHandler);
+ geoMap.removeMouseMoveListener(this.mouseHandler);
+ geoMap.removeMouseTrackListener(this.mouseHandler);
+ geoMap.removeMouseWheelListener(this.mouseHandler);
+ }
+ this.mouseHandler = mouseHandler;
+ if (this.mouseHandler != null) {
+ geoMap.addMouseListener(this.mouseHandler);
+ geoMap.addMouseMoveListener(this.mouseHandler);
+ geoMap.addMouseTrackListener(this.mouseHandler);
+ geoMap.addMouseWheelListener(this.mouseHandler);
+ }
+ }
+
+ /**
+ * Creates a GeoMapViewer with a default GeoMap inside a specific Composite
+ * @param parent the parent Composite
+ * @param flags the SWT options
+ */
+ public GeoMapViewer(Composite parent, int flags) {
+ this(new GeoMap(parent, flags));
+ }
+
+ @Override
+ protected void handleDispose(DisposeEvent event) {
+ super.handleDispose(event);
+ }
+
+ @Override
+ protected void handleLabelProviderChanged(LabelProviderChangedEvent event) {
+ super.handleLabelProviderChanged(event);
+ refresh();
+ }
+
+ /**
+ * Returns the location provider for this GeoMapViewer.
+ * @return the location provider
+ */
+ public LocationProvider getLocationProvider() {
+ return locationProvider;
+ }
+
+ /**
+ * Sets the location provider for this GeoMapViewer. The location provider determines where the icon for each element is placed.
+ * @param locationProvider the location provider
+ */
+ public void setLocationProvider(LocationProvider locationProvider) {
+ this.locationProvider = locationProvider;
+ }
+
+ //
+
+ protected void paintOverlay(PaintEvent e) {
+ doContents(e.gc, null, selection);
+ if (mouseHandler != null) {
+ mouseHandler.paintControl(e);
+ }
+ }
+
+ private Object doContents(GC gc, Rectangle contain, Object selection) {
+// System.out.println(mapWidget.getMapPosition() + "/" + mapWidget.getCenterPosition() + "@" + mapWidget.getZoom());
+ IContentProvider contentProvider = getContentProvider();
+ Object[] contents = (contentProvider instanceof IStructuredContentProvider ? ((IStructuredContentProvider) contentProvider).getElements(getInput()) : null);
+ if (contents != null && getLocationProvider() != null) {
+ for (int i = 0; i < contents.length; i++) {
+ Object element = contents[i];
+ Object found = doContent(element, gc, contain, selection);
+ if (found != null) {
+ return found;
+ }
+ }
+ }
+ return null;
+ }
+
+ private Object doContent(Object element, GC gc, Rectangle contain, Object selection) {
+ Point p = getElementPosition(element, null, true, true);
+ if (p == null) {
+ return null;
+ }
+ IBaseLabelProvider labelProvider = getLabelProvider();
+ Image image = null;
+ if (labelProvider instanceof ILabelProvider) {
+ @SuppressWarnings("unused")
+ String text = ((ILabelProvider) labelProvider).getText(element);
+ image = ((ILabelProvider) labelProvider).getImage(element);
+ }
+ if (image == null) {
+ return null;
+ }
+ Rectangle bounds = image.getBounds();
+ bounds.x = p.x;
+ bounds.y = p.y;
+ if (gc != null) {
+ boolean isSelected = selection != null && element == selection;
+ if (isSelected && selectionOffset != null) {
+ bounds.x += selectionOffset.x;
+ bounds.y += selectionOffset.y;
+ }
+ gc.drawImage(image, bounds.x, bounds.y);
+ if (isSelected) {
+ gc.drawRectangle(bounds.x, bounds.y, bounds.width, bounds.height);
+ }
+ }
+ if (contain != null && bounds.contains(contain.x, contain.y) && bounds.contains(contain.x + contain.width, contain.y + contain.height)) {
+ return element;
+ }
+ return null;
+ }
+
+ private Point getElementPosition(Object element, Point into, boolean mapRelative, boolean imageRelative) {
+ PointD lonLat = (element instanceof PointD ? (PointD) element : getLocationProvider().getLonLat(element));
+ if (lonLat == null) {
+ return null;
+ }
+ int x = GeoMap.lon2position(lonLat.x, geoMap.getZoom());
+ int y = GeoMap.lat2position(lonLat.y, geoMap.getZoom());
+ if (mapRelative) {
+ Point p = geoMap.getMapPosition();
+ x -= p.x;
+ y -= p.y;
+ }
+ if (imageRelative) {
+ IBaseLabelProvider labelProvider = getLabelProvider();
+ if (labelProvider instanceof IPinPointProvider) {
+ Point p = ((IPinPointProvider) labelProvider).getPinPoint(element);
+ if (p != null) {
+ x -= p.x;
+ y -= p.y;
+ }
+ }
+ }
+ if (into == null) {
+ into = new Point(x, y);
+ } else {
+ into.x = x;
+ into.y = y;
+ }
+ return into;
+ }
+
+ @Override
+ public Control getControl() {
+ return getGeoMap();
+ }
+
+ /**
+ * Returns the underlying GeoMap control
+ * @return the underlying GeoMap control
+ */
+ public GeoMap getGeoMap() {
+ return geoMap;
+ }
+
+ @Override
+ public ISelection getSelection() {
+ return (selection != null ? new StructuredSelection(selection) : StructuredSelection.EMPTY);
+ }
+
+ @Override
+ public void refresh() {
+ geoMap.redraw();
+ }
+
+ @Override
+ public void setSelection(ISelection selection, boolean reveal) {
+ setSelection(selection instanceof IStructuredSelection ? ((IStructuredSelection) selection).getFirstElement() : null);
+ if (reveal && this.selection != null) {
+ reveal(this.selection, true);
+ }
+ }
+
+ private int centerOnSelectionMargin = 10;
+
+ private void reveal(Object selection, boolean center) {
+ Point position = getElementPosition(selection, new Point(0, 0), true, false);
+ Point size = geoMap.getSize();
+ Rectangle insideMargin = new Rectangle(centerOnSelectionMargin, centerOnSelectionMargin, size.x - centerOnSelectionMargin, size.y - centerOnSelectionMargin);
+ if (position != null && (center || (! insideMargin.contains(position)))) {
+ Point mapPosition = geoMap.getMapPosition();
+ geoMap.setCenterPosition(new Point(position.x + mapPosition.x, position.y + mapPosition.y));
+ }
+ }
+
+ private void setSelection(Object selection) {
+ this.selection = selection;
+ refresh();
+ }
+
+ //
+
+ private class MovePinMouseHandler extends DefaultMouseHandler {
+
+ MovePinMouseHandler(GeoMap geoMap) {
+ super(geoMap);
+ }
+
+ private boolean checkReadOnlyImmediate = false;
+ private int thumbSize = 7;
+
+ private Rectangle createPointRectangle(int x, int y) {
+ return new Rectangle(x - thumbSize / 2, y - thumbSize / 2, thumbSize, thumbSize);
+ }
+
+ protected boolean isPanDownEvent(MouseEvent e) {
+ return super.isPanDownEvent(e) && doContents(null, createPointRectangle(e.x, e.y), null) == null;
+ }
+
+ protected boolean handleDown(MouseEvent e) {
+ boolean redraw = super.handleDown(e);
+ Object contains = doContents(null, createPointRectangle(e.x, e.y), null);
+ if (contains != null) {
+ selectionOffset = new Point(0, 0);
+ PointD lonLat = getLocationProvider().getLonLat(contains);
+ if (checkReadOnlyImmediate && (! getLocationProvider().setLonLat(contains, lonLat.x, lonLat.y))) {
+ selectionOffset = null;
+ }
+ setSelection(contains);
+ redraw = true;
+ }
+ return redraw;
+ }
+
+ @Override
+ protected boolean handleDrag(MouseEvent e) {
+ boolean redraw = super.handleDrag(e);
+ if (selectionOffset != null) {
+ selectionOffset.x = e.x - downCoords.x;
+ selectionOffset.y = e.y - downCoords.y;
+ return true;
+ }
+ return redraw;
+ }
+
+ @Override
+ protected boolean handleUp(MouseEvent e) {
+ boolean redraw = super.handleUp(e);
+ if (selectionOffset != null) {
+ Point oldPosition = getElementPosition(selection, new Point(0, 0), false, false);
+ Point newPosition = new Point(oldPosition.x + selectionOffset.x, oldPosition.y + selectionOffset.y);
+ PointD lonLat = geoMap.getLongitudeLatitude(newPosition);
+ @SuppressWarnings("unused")
+ boolean changed = getLocationProvider().setLonLat(selection, lonLat.x, lonLat.y);
+ reveal(selection, (e.stateMask & SWT.CTRL) != 0);
+ selectionOffset = null;
+ redraw = true;
+ }
+ return redraw;
+ }
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/GoogleIconDescriptor.java b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/GoogleIconDescriptor.java
new file mode 100644
index 0000000..89a7450
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/GoogleIconDescriptor.java
@@ -0,0 +1,146 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Hallvard Trūtteberg.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hallvard Trūtteberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.nebula.jface.geomap;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.jface.resource.ImageDescriptor;
+import org.eclipse.jface.resource.ImageRegistry;
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.RGB;
+
+/**
+ * ImageDescriptor that downloads the image data from https://chart.googleapis.com/
+ * Typically used by a LabelProvider with an ImageRegistry to provide map icons.
+ * @see LabelProvider
+ * @see ImageRegistry
+ * @author hal
+ *
+ */
+public class GoogleIconDescriptor extends ImageDescriptor {
+
+ private String iconClass, iconName, style;
+ private boolean hasShadow;
+ private String text;
+ private RGB fillColor = new RGB(0, 255, 0), textColor = new RGB(0, 0, 0);
+
+ public GoogleIconDescriptor(String iconClass, String iconName,
+ String style, boolean hasShadow, String text, RGB fillColor,
+ RGB textColor) {
+ super();
+ this.iconClass = iconClass;
+ this.iconName = iconName;
+ this.style = style;
+ this.hasShadow = hasShadow;
+ this.text = text;
+ this.fillColor = fillColor;
+ this.textColor = textColor;
+ }
+
+ public GoogleIconDescriptor(String iconClass, String iconName,
+ String style, boolean hasShadow, String text) {
+ this.iconClass = iconClass;
+ this.iconName = iconName;
+ this.style = style;
+ this.hasShadow = hasShadow;
+ this.text = text;
+ }
+
+ private static String baseUrl = "https://chart.googleapis.com/chart?";
+ private static String argsSep = "|";
+
+ @Override
+ public ImageData getImageData() {
+ String chst = this.iconClass;
+ if (hasShadow) {
+ chst += "_withshadow";
+ }
+ Object[] args = {iconName, style, text, toHex(fillColor), toHex(textColor)};
+ StringBuilder chld = new StringBuilder();
+ for (int i = 0; i < args.length; i++) {
+ if (args[i] != null) {
+ if (chld.length() > 0) {
+ chld.append(argsSep);
+ }
+ chld.append(args[i]);
+ }
+ }
+ try {
+ return getImageData(baseUrl + "chst=" + chst + "&chld=" + chld);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ private String toHex(RGB rgb) {
+ return String.format("%02x%02x%02x", rgb.red, rgb.green, rgb.blue);
+ }
+
+ public ImageData getImageData(String urlString) {
+ InputStream inputStream = null;
+ try {
+ System.out.println(urlString);
+ inputStream = new URL(urlString).openStream();
+ return new ImageData(inputStream);
+ } catch (MalformedURLException e) {
+ throw new IllegalArgumentException(e);
+ } catch (IOException e) {
+ throw new IllegalArgumentException(e);
+ } finally {
+ if (inputStream != null) {
+ try {
+ inputStream.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ }
+
+ //
+
+ public final static String icon_map_pin_letter = "d_map_pin_letter";
+ public final static String icon_bubble_text_small = "d_bubble_text_small";
+ public final static String icon_bubble_icon_text_small = "d_bubble_icon_text_small";
+
+ public final static String icon_style_pin = "pin";
+ public final static String icon_style_pin_star = "pin_star";
+ public final static String icon_style_pin_sleft = "pin_sleft";
+ public final static String icon_style_pin_sright = "pin_sright";
+
+ public final static String frame_style_bb = "bb";
+ public final static String frame_style_bbtl = "bbtl";
+ public final static String frame_style_bbtr = "bbtr";
+ public final static String frame_style_bbbr = "bbbr";
+ public final static String frame_style_bbT = "bbT";
+
+ public final static String frame_style_edge_bl = "edge_bl";
+ public final static String frame_style_edge_bc = "edge_bc";
+ public final static String frame_style_edge_br = "edge_br";
+ public final static String frame_style_edge_tl = "edge_tl";
+ public final static String frame_style_edge_tc = "edge_tc";
+ public final static String frame_style_edge_tr = "edge_tr";
+ public final static String frame_style_edge_lt = "edge_lt";
+ public final static String frame_style_edge_lc = "edge_lc";
+ public final static String frame_style_edge_lb = "edge_lb";
+ public final static String frame_style_edge_rt = "edge_rt";
+ public final static String frame_style_edge_rc = "edge_rc";
+ public final static String frame_style_edge_rb = "edge_rb";
+
+ public static GoogleIconDescriptor letterPin(char c, boolean hasShadow, RGB fillColor, RGB textColor)
+ { return new GoogleIconDescriptor(icon_map_pin_letter, null, null, hasShadow, String.valueOf(c), fillColor, textColor);}
+
+ public static GoogleIconDescriptor letterPin(char c, boolean hasShadow, RGB fillColor)
+ { return letterPin(c, hasShadow, fillColor, new RGB(0, 0, 0));}
+}
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/IPinPointProvider.java b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/IPinPointProvider.java
new file mode 100644
index 0000000..44c306e
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/IPinPointProvider.java
@@ -0,0 +1,31 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Hallvard Trūtteberg.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hallvard Trūtteberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.nebula.jface.geomap;
+
+import org.eclipse.jface.viewers.ILabelProvider;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Interface for telling a GeoMapViewer the position of the tip of an icon, e.g. a pin,
+ * relative to the icon's topleft corner. Since the GeoMapViewer does not have a separate
+ * IPinPointProvider, your ILabelProvider should implement this interface to properly
+ * position the icon.
+ * @author hal
+ *
+ */
+public interface IPinPointProvider {
+ /**
+ * Provides the relative position of the hot spot for the an image of an element, e.g. a pin on a map.
+ * @param element the element for which to find the hot spot
+ * @return the relative position, or null for 0, 0
+ */
+ public Point getPinPoint(Object element);
+}
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/LocationProvider.java b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/LocationProvider.java
new file mode 100644
index 0000000..98bff97
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/LocationProvider.java
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Hallvard Trūtteberg.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hallvard Trūtteberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.nebula.jface.geomap;
+
+import org.eclipse.nebula.widgets.geomap.PointD;
+
+/**
+ * Interface to provide a location for a given element, as a PointD with longitude, latitude coordinates.
+ *
+ */
+public interface LocationProvider {
+ /*
+ * Returns the longitude, latitude for the element
+ * or null if this elements doesn't have a location.
+ */
+ public PointD getLonLat(Object element);
+
+ /*
+ * Set the longitude, latitude for the element.
+ * Returns true if the change occurred, i.e. the operation was legal.
+ * Use setLonLat(element, getLon(element), getLat(element)) to check without side-effect.
+ */
+ public boolean setLonLat(Object element, double lon, double lat);
+}
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/MouseHandler.java b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/MouseHandler.java
new file mode 100644
index 0000000..f65e540
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/MouseHandler.java
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Hallvard Trūtteberg.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hallvard Trūtteberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.nebula.jface.geomap;
+
+import org.eclipse.nebula.widgets.geomap.GeoMap;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.MouseWheelListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Point;
+
+/**
+ * Handles mouse interaction, on behalf of a GeoMapViewer. Makes it easier to customize the viewer.
+ *
+ * @author hal
+ *
+ */
+class MouseHandler implements MouseListener, MouseMoveListener, MouseTrackListener, MouseWheelListener, PaintListener {
+
+ protected final GeoMap geoMap;
+
+ /**
+ * @param geoMap
+ */
+ MouseHandler(GeoMap geoMap) {
+ this.geoMap = geoMap;
+ }
+
+ public void mouseEnter(MouseEvent e) {
+ this.geoMap.forceFocus();
+ }
+ public void mouseExit(MouseEvent e) {
+ }
+
+ protected Point dragCoords;
+ protected Point downCoords;
+
+ public final void mouseDown(MouseEvent e) {
+ dragCoords = new Point(e.x, e.y);
+ downCoords = new Point(e.x, e.y);
+ if (handleDown(e)) {
+ this.geoMap.redraw();
+ }
+ }
+
+ public final void mouseMove(MouseEvent e) {
+ if (dragCoords != null) {
+ dragCoords.x = e.x;
+ dragCoords.y = e.y;
+ if (handleDrag(e)) {
+ this.geoMap.redraw();
+ }
+ }
+ }
+
+ public final void mouseUp(MouseEvent e) {
+ if (handleUp(e)) {
+ this.geoMap.redraw();
+ }
+ downCoords = null;
+ dragCoords = null;
+ }
+
+ protected boolean handleDown(MouseEvent e) {
+ return false;
+ }
+ protected boolean handleDrag(MouseEvent e) {
+ return false;
+ }
+ protected boolean handleUp(MouseEvent e) {
+ return false;
+ }
+
+ // stubs
+
+ public void mouseHover(MouseEvent e) {
+ }
+
+ public void mouseDoubleClick(MouseEvent e) {
+ }
+
+ public void mouseScrolled(MouseEvent e) {
+ }
+
+ // if handler has own, visual state
+
+ public void paintControl(PaintEvent e) {
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/PinPointProvider.java b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/PinPointProvider.java
new file mode 100644
index 0000000..f361b64
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.jface.geomap/src/org/eclipse/nebula/jface/geomap/PinPointProvider.java
@@ -0,0 +1,61 @@
+/*******************************************************************************
+ * Copyright (c) 2012 Hallvard Trūtteberg.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Hallvard Trūtteberg - initial API and implementation
+ ******************************************************************************/
+package org.eclipse.nebula.jface.geomap;
+
+import org.eclipse.jface.viewers.LabelProvider;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+
+/**
+ * A default implementation of a LabelProvider that also implements IPinPointProvider.
+ * @author hal
+ *
+ */
+public class PinPointProvider extends LabelProvider implements IPinPointProvider {
+
+ private final Point defaultPinPoint;
+
+ /**
+ * A PinPointProvider that returns the corresponding pin point.
+ * @param x the x coordinate of the point
+ * @param y the y coordinate of the point
+ */
+ public PinPointProvider(int x, int y) {
+ defaultPinPoint = new Point(0, 0);
+ }
+
+ /**
+ * A PinPointProvider that returns 0, 0 for the pin point.
+ */
+ public PinPointProvider() {
+ this(0, 0);
+ }
+
+ /**
+ * The default implementation just returns the value of the defaultPinPoint field.
+ */
+ public Point getPinPoint(Object element) {
+ return defaultPinPoint;
+ }
+
+ /**
+ * Helper method for computing the point based on the size of the image.
+ * The float arguments alignX and alignY are multiplied with the width and height of the image, respectively.
+ * @param element the element to provide the point for
+ * @param alignX a float that is multiplied with the width of the image, to give the x coordinate of the point
+ * @param alignY a float that is multiplied with the height of the image, to give the y coordinate of the point
+ * @return
+ */
+ protected Point getPinPoint(Object element, float alignX, float alignY) {
+ Rectangle bounds = getImage(element).getBounds();
+ return new Point((int) (bounds.width * alignX), (int) (bounds.height * alignY));
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/.cvsignore b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/.cvsignore
new file mode 100644
index 0000000..eb5a316
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/.cvsignore
@@ -0,0 +1 @@
+target
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/.project b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/.project
new file mode 100644
index 0000000..3ee016c
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.nebula.widgets.geomap.feature</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.pde.FeatureBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.FeatureNature</nature>
+ </natures>
+</projectDescription>
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/build.properties b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/build.properties
new file mode 100644
index 0000000..64f93a9
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/build.properties
@@ -0,0 +1 @@
+bin.includes = feature.xml
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/feature.xml b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/feature.xml
new file mode 100644
index 0000000..5fcb019
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/feature.xml
@@ -0,0 +1,51 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feature
+ id="org.eclipse.nebula.widgets.geomap.feature"
+ label="Nebula GeoMap Widget and Viewer"
+ version="0.1.0.qualifier">
+
+ <description url="http://www.eclipse.org/nebula/widgets/geomap">
+ A Date and Time selection widgt that can be used in a textual, graphical, or combo mode.
+ </description>
+
+ <copyright url="http://www.example.com/copyright">
+ [Enter Copyright Description here.]
+ </copyright>
+
+ <license url="http://www.example.com/license">
+ [Enter License Description here.]
+ </license>
+
+ <requires>
+ <import feature="org.eclipse.nebula.cwt.feature" version="0.9.0.qualifier"/>
+ </requires>
+
+ <plugin
+ id="org.eclipse.nebula.widgets.geomap"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.nebula.widgets.geomap.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.nebula.jface.geomap.source"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+ <plugin
+ id="org.eclipse.nebula.jface.geomap"
+ download-size="0"
+ install-size="0"
+ version="0.0.0"
+ unpack="false"/>
+
+</feature>
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/pom.xml b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/pom.xml
new file mode 100644
index 0000000..970d5a3
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.feature/pom.xml
@@ -0,0 +1,18 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <artifactId>nebula-parent</artifactId>
+ <groupId>org.eclipse.nebula</groupId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../../../releng/org.eclipse.nebula.nebula-parent</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.nebula</groupId>
+ <artifactId>org.eclipse.nebula.widgets.geomap.feature</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <packaging>eclipse-feature</packaging>
+
+</project> \ No newline at end of file
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.classpath b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.classpath
new file mode 100644
index 0000000..64c5e31
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.cvsignore b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.cvsignore
new file mode 100644
index 0000000..eb5a316
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.cvsignore
@@ -0,0 +1 @@
+target
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.project b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.project
new file mode 100644
index 0000000..e2d6500
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.nebula.widgets.geomap.snippets</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.settings/org.eclipse.jdt.core.prefs b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..8a9bde0
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,7 @@
+#Sat Jun 28 08:48:22 MDT 2008
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.source=1.5
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/META-INF/MANIFEST.MF b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..ce18de6
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/META-INF/MANIFEST.MF
@@ -0,0 +1,12 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.nebula.widgets.geomap.snippets
+Bundle-Version: 0.1.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Export-Package: org.eclipse.nebula.widgets.geomap.snippets
+Require-Bundle: org.eclipse.jface,
+ org.eclipse.ui.forms,
+ org.eclipse.nebula.widgets.geomap
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/about.html b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/about.html
new file mode 100644
index 0000000..c258ef5
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/build.properties b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/build.properties
new file mode 100644
index 0000000..34d2e4d
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/build.properties
@@ -0,0 +1,4 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/plugin.properties b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/plugin.properties
new file mode 100644
index 0000000..bc467be
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/plugin.properties
@@ -0,0 +1,2 @@
+pluginName = CDatetime Snippets Plugin (Incubation)
+providerName = Eclipse.org
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/pom.xml b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/pom.xml
new file mode 100644
index 0000000..2495cf5
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>nebula-parent</artifactId>
+ <groupId>org.eclipse.nebula</groupId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../../../releng/org.eclipse.nebula.nebula-parent</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.nebula</groupId>
+ <artifactId>org.eclipse.nebula.widgets.geomap.snippets</artifactId>
+ <version>0.9.0-SNAPSHOT</version>
+ <packaging>eclipse-plugin</packaging>
+
+</project>
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/src/org/eclipse/nebula/widgets/geomap/snippets/GeoMapBrowserSnippet01.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/src/org/eclipse/nebula/widgets/geomap/snippets/GeoMapBrowserSnippet01.java
new file mode 100644
index 0000000..6b4bbb8
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/src/org/eclipse/nebula/widgets/geomap/snippets/GeoMapBrowserSnippet01.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap.snippets;
+
+import org.eclipse.nebula.widgets.geomap.GeoMapBrowser;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+public class GeoMapBrowserSnippet01 {
+
+ public static void main (String [] args) throws Exception {
+ Display display = new Display ();
+ Shell shell = new Shell(display);
+ shell.setText("Map Widget - SWT Native Map Browsing, Map data from openstreetmap.org");
+ shell.setSize(600, 710);
+ shell.setLocation(10, 10);
+ shell.setLayout (new FillLayout());
+
+ new GeoMapBrowser(shell, SWT.NONE);
+ shell.open ();
+ while (! shell.isDisposed ()) {
+ if (! display.readAndDispatch()) {
+ display.sleep ();
+ }
+ }
+ display.dispose ();
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/src/org/eclipse/nebula/widgets/geomap/snippets/GeoMapSnippet01.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/src/org/eclipse/nebula/widgets/geomap/snippets/GeoMapSnippet01.java
new file mode 100644
index 0000000..7b9c61f
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap.snippets/src/org/eclipse/nebula/widgets/geomap/snippets/GeoMapSnippet01.java
@@ -0,0 +1,39 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap.snippets;
+
+import org.eclipse.nebula.widgets.geomap.GeoMap;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+public class GeoMapSnippet01 {
+
+ public static void main (String [] args) throws Exception {
+ Display display = new Display ();
+ Shell shell = new Shell(display);
+ shell.setText("GeoMap Widget - SWT Native Map Browsing, Map data from openstreetmap.org");
+ shell.setSize(600, 710);
+ shell.setLocation(10, 10);
+ shell.setLayout (new FillLayout());
+
+ new GeoMap(shell, SWT.NONE);
+ shell.open ();
+ while (! shell.isDisposed ()) {
+ if (! display.readAndDispatch()) {
+ display.sleep ();
+ }
+ }
+ display.dispose ();
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/.classpath b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.classpath
new file mode 100644
index 0000000..64c5e31
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.classpath
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/.project b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.project
new file mode 100644
index 0000000..e98678e
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.project
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.nebula.widgets.geomap</name>
+ <comment></comment>
+ <projects>
+ </projects>
+ <buildSpec>
+ <buildCommand>
+ <name>org.eclipse.jdt.core.javabuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.ManifestBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ <buildCommand>
+ <name>org.eclipse.pde.SchemaBuilder</name>
+ <arguments>
+ </arguments>
+ </buildCommand>
+ </buildSpec>
+ <natures>
+ <nature>org.eclipse.pde.PluginNature</nature>
+ <nature>org.eclipse.jdt.core.javanature</nature>
+ </natures>
+</projectDescription>
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.jdt.core.prefs b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..79513c2
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,350 @@
+#Sun Jan 11 12:09:03 MST 2009
+eclipse.preferences.version=1
+org.eclipse.jdt.core.builder.cleanOutputFolder=clean
+org.eclipse.jdt.core.builder.duplicateResourceTask=warning
+org.eclipse.jdt.core.builder.invalidClasspath=abort
+org.eclipse.jdt.core.builder.recreateModifiedClassFileInOutputFolder=ignore
+org.eclipse.jdt.core.builder.resourceCopyExclusionFilter=*.launch,*.testsuite,*.deploy,*.location,*.execution,*.datapool,*.artifact,*.html,*.svg
+org.eclipse.jdt.core.circularClasspath=error
+org.eclipse.jdt.core.classpath.exclusionPatterns=enabled
+org.eclipse.jdt.core.classpath.multipleOutputLocations=enabled
+org.eclipse.jdt.core.codeComplete.argumentPrefixes=
+org.eclipse.jdt.core.codeComplete.argumentSuffixes=
+org.eclipse.jdt.core.codeComplete.fieldPrefixes=
+org.eclipse.jdt.core.codeComplete.fieldSuffixes=
+org.eclipse.jdt.core.codeComplete.localPrefixes=
+org.eclipse.jdt.core.codeComplete.localSuffixes=
+org.eclipse.jdt.core.codeComplete.staticFieldPrefixes=
+org.eclipse.jdt.core.codeComplete.staticFieldSuffixes=
+org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
+org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
+org.eclipse.jdt.core.compiler.compliance=1.5
+org.eclipse.jdt.core.compiler.debug.lineNumber=generate
+org.eclipse.jdt.core.compiler.debug.localVariable=generate
+org.eclipse.jdt.core.compiler.debug.sourceFile=generate
+org.eclipse.jdt.core.compiler.doc.comment.support=enabled
+org.eclipse.jdt.core.compiler.maxProblemPerUnit=100
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning
+org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=warning
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=enabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=warning
+org.eclipse.jdt.core.compiler.problem.emptyStatement=warning
+org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=enabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=warning
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=error
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=warning
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadoc=warning
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled
+org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=warning
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingJavadocComments=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=warning
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=warning
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=warning
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=warning
+org.eclipse.jdt.core.compiler.problem.nullReference=warning
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=warning
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=warning
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=warning
+org.eclipse.jdt.core.compiler.problem.unusedLabel=warning
+org.eclipse.jdt.core.compiler.problem.unusedLocal=warning
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=warning
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=warning
+org.eclipse.jdt.core.compiler.source=1.5
+org.eclipse.jdt.core.formatter.align_type_members_on_columns=false
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_assignment=0
+org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16
+org.eclipse.jdt.core.formatter.alignment_for_compact_if=16
+org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0
+org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16
+org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16
+org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16
+org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16
+org.eclipse.jdt.core.formatter.blank_lines_after_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_after_package=1
+org.eclipse.jdt.core.formatter.blank_lines_before_field=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=1
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1
+org.eclipse.jdt.core.formatter.blank_lines_before_method=1
+org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1
+org.eclipse.jdt.core.formatter.blank_lines_before_package=0
+org.eclipse.jdt.core.formatter.blank_lines_between_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1
+org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line
+org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=false
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true
+org.eclipse.jdt.core.formatter.comment.indent_root_tags=true
+org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert
+org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert
+org.eclipse.jdt.core.formatter.comment.line_length=80
+org.eclipse.jdt.core.formatter.compact_else_if=true
+org.eclipse.jdt.core.formatter.continuation_indentation=2
+org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2
+org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true
+org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true
+org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_empty_lines=false
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true
+org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true
+org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert
+org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert
+org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert
+org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert
+org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert
+org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert
+org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_throw=insert
+org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert
+org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert
+org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert
+org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert
+org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0
+org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true
+org.eclipse.jdt.core.formatter.tabulation.char=tab
+org.eclipse.jdt.core.formatter.tabulation.size=4
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
+org.eclipse.jdt.core.incompatibleJDKLevel=ignore
+org.eclipse.jdt.core.incompleteClasspath=error
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.jdt.ui.prefs b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..28f6fc2
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,106 @@
+#Fri Jul 27 16:09:24 EDT 2007
+cleanup.add_default_serial_version_id=true
+cleanup.add_generated_serial_version_id=false
+cleanup.add_missing_annotations=false
+cleanup.add_missing_deprecated_annotations=true
+cleanup.add_missing_nls_tags=false
+cleanup.add_missing_override_annotations=true
+cleanup.add_serial_version_id=false
+cleanup.always_use_blocks=true
+cleanup.always_use_parentheses_in_expressions=true
+cleanup.always_use_this_for_non_static_field_access=false
+cleanup.always_use_this_for_non_static_method_access=false
+cleanup.convert_to_enhanced_for_loop=false
+cleanup.format_source_code=false
+cleanup.make_local_variable_final=true
+cleanup.make_parameters_final=false
+cleanup.make_private_fields_final=true
+cleanup.make_variable_declarations_final=false
+cleanup.never_use_blocks=false
+cleanup.never_use_parentheses_in_expressions=false
+cleanup.organize_imports=true
+cleanup.qualify_static_field_accesses_with_declaring_class=false
+cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+cleanup.qualify_static_member_accesses_with_declaring_class=true
+cleanup.qualify_static_method_accesses_with_declaring_class=false
+cleanup.remove_private_constructors=true
+cleanup.remove_trailing_whitespaces=true
+cleanup.remove_trailing_whitespaces_all=false
+cleanup.remove_trailing_whitespaces_ignore_empty=true
+cleanup.remove_unnecessary_casts=true
+cleanup.remove_unnecessary_nls_tags=true
+cleanup.remove_unused_imports=true
+cleanup.remove_unused_local_variables=false
+cleanup.remove_unused_private_fields=true
+cleanup.remove_unused_private_members=false
+cleanup.remove_unused_private_methods=true
+cleanup.remove_unused_private_types=true
+cleanup.sort_members=false
+cleanup.sort_members_all=false
+cleanup.use_blocks=true
+cleanup.use_blocks_only_for_return_and_throw=false
+cleanup.use_parentheses_in_expressions=false
+cleanup.use_this_for_non_static_field_access=false
+cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+cleanup.use_this_for_non_static_method_access=false
+cleanup.use_this_for_non_static_method_access_only_if_necessary=true
+cleanup_profile=_Eclipse [modified 1.4]
+cleanup_settings_version=2
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=false
+formatter_profile=org.eclipse.jdt.ui.default.eclipse_profile
+formatter_settings_version=11
+org.eclipse.jdt.ui.exception.name=e
+org.eclipse.jdt.ui.gettersetter.use.is=true
+org.eclipse.jdt.ui.javadoc=true
+org.eclipse.jdt.ui.keywordthis=false
+org.eclipse.jdt.ui.overrideannotation=false
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates><template autoinsert\="true" context\="gettercomment_context" deleted\="false" description\="Comment for getter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.gettercomment" name\="gettercomment">/**\r\n * @return Returns the ${bare_field_name}.\r\n */</template><template autoinsert\="true" context\="settercomment_context" deleted\="false" description\="Comment for setter method" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.settercomment" name\="settercomment">/**\r\n * @param ${param} The ${bare_field_name} to set.\r\n */</template><template autoinsert\="true" context\="constructorcomment_context" deleted\="false" description\="Comment for created constructors" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorcomment" name\="constructorcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="filecomment_context" deleted\="false" description\="Comment for created Java files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.filecomment" name\="filecomment">/*******************************************************************************\r\n * Copyright (c) ${year} IBM Corporation and others.\r\n * All rights reserved. This program and the accompanying materials\r\n * are made available under the terms of the Eclipse Public License v1.0\r\n * which accompanies this distribution, and is available at\r\n * http\\\://www.eclipse.org/legal/epl-v10.html\r\n *\r\n * Contributors\\\:\r\n * IBM Corporation - initial API and implementation\r\n ******************************************************************************/\r\n</template><template autoinsert\="false" context\="typecomment_context" deleted\="false" description\="Comment for created types" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.typecomment" name\="typecomment">/**\r\n * @since 3.3\r\n *\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="fieldcomment_context" deleted\="false" description\="Comment for fields" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.fieldcomment" name\="fieldcomment">/**\r\n * \r\n */</template><template autoinsert\="true" context\="methodcomment_context" deleted\="false" description\="Comment for non-overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodcomment" name\="methodcomment">/**\r\n * ${tags}\r\n */</template><template autoinsert\="true" context\="overridecomment_context" deleted\="false" description\="Comment for overriding methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.overridecomment" name\="overridecomment">/* (non-Javadoc)\r\n * ${see_to_overridden}\r\n */</template><template autoinsert\="true" context\="delegatecomment_context" deleted\="false" description\="Comment for delegate methods" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.delegatecomment" name\="delegatecomment">/**\r\n * ${tags}\r\n * ${see_to_target}\r\n */</template><template autoinsert\="true" context\="newtype_context" deleted\="false" description\="Newly created files" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.newtype" name\="newtype">${filecomment}\r\n${package_declaration}\r\n\r\n${typecomment}\r\n${type_declaration}</template><template autoinsert\="true" context\="classbody_context" deleted\="false" description\="Code in new class type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.classbody" name\="classbody">\r\n</template><template autoinsert\="true" context\="interfacebody_context" deleted\="false" description\="Code in new interface type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.interfacebody" name\="interfacebody">\r\n</template><template autoinsert\="true" context\="enumbody_context" deleted\="false" description\="Code in new enum type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.enumbody" name\="enumbody">\r\n</template><template autoinsert\="true" context\="annotationbody_context" deleted\="false" description\="Code in new annotation type bodies" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.annotationbody" name\="annotationbody">\r\n</template><template autoinsert\="true" context\="catchblock_context" deleted\="false" description\="Code in new catch blocks" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.catchblock" name\="catchblock">// ${todo} Auto-generated catch block\r\n${exception_var}.printStackTrace();</template><template autoinsert\="true" context\="methodbody_context" deleted\="false" description\="Code in created method stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.methodbody" name\="methodbody">// ${todo} Auto-generated method stub\r\n${body_statement}</template><template autoinsert\="true" context\="constructorbody_context" deleted\="false" description\="Code in created constructor stubs" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.constructorbody" name\="constructorbody">${body_statement}\r\n// ${todo} Auto-generated constructor stub</template><template autoinsert\="true" context\="getterbody_context" deleted\="false" description\="Code in created getters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.getterbody" name\="getterbody">return ${field};</template><template autoinsert\="true" context\="setterbody_context" deleted\="false" description\="Code in created setters" enabled\="true" id\="org.eclipse.jdt.ui.text.codetemplates.setterbody" name\="setterbody">${field} \= ${param};</template></templates>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=true
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.format_source_code=false
+sp_cleanup.make_local_variable_final=false
+sp_cleanup.make_parameters_final=false
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_variable_declarations_final=true
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=false
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=true
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.ltk.core.refactoring.prefs b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.ltk.core.refactoring.prefs
new file mode 100644
index 0000000..4004f36
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.ltk.core.refactoring.prefs
@@ -0,0 +1,3 @@
+#Fri Jul 27 17:01:55 EDT 2007
+eclipse.preferences.version=1
+org.eclipse.ltk.core.refactoring.enable.project.refactoring.history=true
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.mylyn.tasks.ui.prefs b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.mylyn.tasks.ui.prefs
new file mode 100644
index 0000000..9fefb52
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.mylyn.tasks.ui.prefs
@@ -0,0 +1,4 @@
+#Fri Jul 27 15:55:02 EDT 2007
+eclipse.preferences.version=1
+project.repository.kind=bugzilla
+project.repository.url=https\://bugs.eclipse.org/bugs
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.pde.prefs b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.pde.prefs
new file mode 100644
index 0000000..a1762dc
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.pde.prefs
@@ -0,0 +1,15 @@
+#Fri Jul 27 15:55:01 EDT 2007
+compilers.incompatible-environment=1
+compilers.p.build=1
+compilers.p.deprecated=1
+compilers.p.missing-packages=2
+compilers.p.no-required-att=0
+compilers.p.not-externalized-att=1
+compilers.p.unknown-attribute=1
+compilers.p.unknown-class=0
+compilers.p.unknown-element=1
+compilers.p.unknown-resource=0
+compilers.p.unresolved-ex-points=0
+compilers.p.unresolved-import=0
+compilers.use-project=true
+eclipse.preferences.version=1
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.wst.validation.prefs b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.wst.validation.prefs
new file mode 100644
index 0000000..60fc80e
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/.settings/org.eclipse.wst.validation.prefs
@@ -0,0 +1,6 @@
+#Fri Jul 27 15:55:02 EDT 2007
+DELEGATES_PREFERENCE=delegateValidatorListorg.eclipse.wst.xsd.core.internal.validation.eclipse.XSDDelegatingValidator\=org.eclipse.wst.xsd.core.internal.validation.eclipse.Validator;
+USER_BUILD_PREFERENCE=enabledBuildValidatorList
+USER_MANUAL_PREFERENCE=enabledManualValidatorList
+USER_PREFERENCE=overrideGlobalPreferencesfalse
+eclipse.preferences.version=1
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/META-INF/MANIFEST.MF b/widgets/geomap/org.eclipse.nebula.widgets.geomap/META-INF/MANIFEST.MF
new file mode 100644
index 0000000..78c7d14
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/META-INF/MANIFEST.MF
@@ -0,0 +1,10 @@
+Manifest-Version: 1.0
+Bundle-ManifestVersion: 2
+Bundle-SymbolicName: org.eclipse.nebula.widgets.geomap
+Bundle-Version: 0.1.0.qualifier
+Bundle-Name: %pluginName
+Bundle-Vendor: %providerName
+Bundle-Localization: plugin
+Bundle-RequiredExecutionEnvironment: J2SE-1.5
+Require-Bundle: org.eclipse.swt
+Export-Package: org.eclipse.nebula.widgets.geomap
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/about.html b/widgets/geomap/org.eclipse.nebula.widgets.geomap/about.html
new file mode 100644
index 0000000..c258ef5
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/about.html
@@ -0,0 +1,28 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
+ "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"/>
+<title>About</title>
+</head>
+<body lang="EN-US">
+<h2>About This Content</h2>
+
+<p>June 5, 2006</p>
+<h3>License</h3>
+
+<p>The Eclipse Foundation makes available all content in this plug-in (&quot;Content&quot;). Unless otherwise
+indicated below, the Content is provided to you under the terms and conditions of the
+Eclipse Public License Version 1.0 (&quot;EPL&quot;). A copy of the EPL is available
+at <a href="http://www.eclipse.org/legal/epl-v10.html">http://www.eclipse.org/legal/epl-v10.html</a>.
+For purposes of the EPL, &quot;Program&quot; will mean the Content.</p>
+
+<p>If you did not receive this Content directly from the Eclipse Foundation, the Content is
+being redistributed by another party (&quot;Redistributor&quot;) and different terms and conditions may
+apply to your use of any object code in the Content. Check the Redistributor's license that was
+provided with the Content. If no such license exists, contact the Redistributor. Unless otherwise
+indicated below, the terms and conditions of the EPL still apply to any source code in the Content
+and such source code may be obtained at <a href="http://www.eclipse.org/">http://www.eclipse.org</a>.</p>
+
+</body>
+</html> \ No newline at end of file
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/build.properties b/widgets/geomap/org.eclipse.nebula.widgets.geomap/build.properties
new file mode 100644
index 0000000..bcc3832
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/build.properties
@@ -0,0 +1,16 @@
+source.. = src/
+output.. = bin/
+bin.includes = META-INF/,\
+ .,\
+ plugin.properties
+nebula.productname=org.eclipse.nebula.widgets.geomap
+javadoc.packages=org.eclipse.nebula.widgets.geomap
+snippets.path=org/eclipse/swt/nebula/widgets/geomap/snippets
+src.includes = plugin.properties,\
+ build.properties,\
+ META-INF/,\
+ .project,\
+ .classpath,\
+ .settings/,\
+ src/,\
+ .refactorings/
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/plugin.properties b/widgets/geomap/org.eclipse.nebula.widgets.geomap/plugin.properties
new file mode 100644
index 0000000..4851ff8
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/plugin.properties
@@ -0,0 +1,2 @@
+pluginName = Nebula GeoMap widget (Incubation)
+providerName = Eclipse.org
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/pom.xml b/widgets/geomap/org.eclipse.nebula.widgets.geomap/pom.xml
new file mode 100644
index 0000000..e3fd2d2
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/pom.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
+ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <artifactId>nebula-parent</artifactId>
+ <groupId>org.eclipse.nebula</groupId>
+ <version>1.0.0-SNAPSHOT</version>
+ <relativePath>../../../releng/org.eclipse.nebula.nebula-parent</relativePath>
+ </parent>
+
+ <groupId>org.eclipse.nebula</groupId>
+ <artifactId>org.eclipse.nebula.widgets.geomap</artifactId>
+ <version>0.1.0-SNAPSHOT</version>
+ <packaging>eclipse-plugin</packaging>
+
+</project>
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/GeoMap.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/GeoMap.java
new file mode 100644
index 0000000..dfcfdb6
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/GeoMap.java
@@ -0,0 +1,714 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap;
+import java.beans.PropertyChangeListener;
+import java.beans.PropertyChangeSupport;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.ConcurrentModificationException;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.Future;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.SWTException;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseListener;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.events.MouseTrackListener;
+import org.eclipse.swt.events.MouseWheelListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Device;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.ImageData;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Shell;
+
+
+
+/**
+ * MapPanel display tiles from openstreetmap as is. This simple minimal viewer supports zoom around mouse-click center and has a simple api.
+ * A number of tiles are cached. See {@link #CACHE_SIZE} constant. If you use this it will create traffic on the tileserver you are
+ * using. Please be conscious about this.
+ *
+ * This class is a JPanel which can be integrated into any swing app just by creating an instance and adding like a JLabel.
+ *
+ * The map has the size <code>256*1<<zoomlevel</code>. This measure is referred to as map-coordinates. Geometric locations
+ * like longitude and latitude can be obtained by helper methods. Note that a point in map-coordinates corresponds to a given
+ * geometric position but also depending on the current zoom level.
+ *
+ * You can zoomIn around current mouse position by left double click. Left right click zooms out.
+ *
+ * <p>
+ * Methods of interest are
+ * <ul>
+ * <li>{@link #setZoom(int)} which sets the map's zoom level. Values between 1 and 18 are allowed.</li>
+ * <li>{@link #setMapPosition(Point)} which sets the map's top left corner. (In map coordinates)</li>
+ * <li>{@link #setCenterPosition(Point)} which sets the map's center position. (In map coordinates)</li>
+ * <li>{@link #computePosition(java.awt.geom.Point2D.Double)} returns the position in the map panels coordinate system
+ * for the given longitude and latitude. If you want to center the map around this geometric location you need
+ * to pass the result to the method</li>
+ * </ul>
+ * </p>
+ *
+ * <p>As mentioned above Longitude/Latitude functionality is available via the method {@link #computePosition(java.awt.geom.Point2D.Double)}.
+ * If you have a GIS database you can get this info out of it for a given town/location, invoke {@link #computePosition(java.awt.geom.Point2D.Double)} to
+ * translate to a position for the given zoom level and center the view around this position using {@link #setCenterPosition(Point)}.
+ * </p>
+ *
+ * <p>The properties <code>zoom</code> and <code>mapPosition</code> are bound and can be tracked via
+ * regular {@link PropertyChangeListener}s.</p>
+ *
+ * <p>License is EPL (Eclipse Public License) http://www.eclipse.org/legal/epl-v10.html. Contact at stepan.rutz@gmx.de</p>
+ *
+ * @author stepan.rutz
+ * @version $Revision$
+ */
+public class GeoMap extends Canvas {
+
+ /*
+ wait icon
+ credits to: RaminusFalcon
+ obtained from: http://commons.wikimedia.org/wiki/File:GreenHourglass_up.svg
+
+ world icon
+ credits to: Zeus
+ http://commons.wikimedia.org/wiki/File:Gartoon-fs-ftp.png
+ */
+
+
+ private static final Logger log = Logger.getLogger(GeoMap.class.getName());
+
+ public static final class TileServer {
+ private final String url;
+ private final int maxZoom;
+ private boolean broken;
+
+ private TileServer(String url, int maxZoom) {
+ this.url = url;
+ this.maxZoom = maxZoom;
+ }
+
+ public String toString() {
+ return url;
+ }
+
+ public int getMaxZoom() {
+ return maxZoom;
+ }
+ public String getURL() {
+ return url;
+ }
+
+ public boolean isBroken() {
+ return broken;
+ }
+
+ public void setBroken(boolean broken) {
+ this.broken = broken;
+ }
+ }
+
+ public static class Stats {
+ public int tileCount;
+ public long dt;
+ private Stats() {
+ reset();
+ }
+ private void reset() {
+ tileCount = 0;
+ dt = 0;
+ }
+ }
+
+ private static class Tile {
+ private final String key;
+ public final int x, y, z;
+ public Tile(String tileServer, int x, int y, int z) {
+ this.key = tileServer;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ }
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((key == null) ? 0 : key.hashCode());
+ result = prime * result + x;
+ result = prime * result + y;
+ result = prime * result + z;
+ return result;
+ }
+ public boolean equals(Object obj) {
+ if (this == obj)
+ return true;
+ if (obj == null)
+ return false;
+ if (getClass() != obj.getClass())
+ return false;
+ Tile other = (Tile) obj;
+ if (key == null) {
+ if (other.key != null)
+ return false;
+ } else if (!key.equals(other.key))
+ return false;
+ if (x != other.x)
+ return false;
+ if (y != other.y)
+ return false;
+ if (z != other.z)
+ return false;
+ return true;
+ }
+ }
+
+ public class TileCache {
+ private LinkedHashMap<Tile,AsyncImage> map = new LinkedHashMap<Tile,AsyncImage>(CACHE_SIZE, 0.75f, true) {
+ protected boolean removeEldestEntry(Map.Entry<Tile,AsyncImage> eldest) {
+ boolean remove = size() > CACHE_SIZE;
+ if (remove)
+ eldest.getValue().dispose(getDisplay());
+ return remove;
+ }
+ };
+ public void put(TileServer tileServer, int x, int y, int z, AsyncImage image) {
+ map.put(new Tile(tileServer.getURL(), x, y, z), image);
+ }
+ public AsyncImage get(TileServer tileServer, int x, int y, int z) {
+ return map.get(new Tile(tileServer.getURL(), x, y, z));
+ }
+ public void remove(TileServer tileServer, int x, int y, int z) {
+ map.remove(new Tile(tileServer.getURL(), x, y, z));
+ }
+ public int getSize() {
+ return map.size();
+ }
+ }
+
+ public final class AsyncImage implements Runnable {
+ private final AtomicReference<ImageData> imageData = new AtomicReference<ImageData>();
+ private Image image; // might as well be thread-local
+ private FutureTask<Boolean> task;
+ private volatile long stamp = zoomStamp.longValue();
+ private final TileServer tileServer;
+ private final int x, y, z;
+
+ public AsyncImage(TileServer tileServer, int x, int y, int z) {
+ this.tileServer = tileServer;
+ this.x = x;
+ this.y = y;
+ this.z = z;
+ task = new FutureTask<Boolean>(this, Boolean.TRUE);
+ executor.execute(task);
+ }
+
+ public void run() {
+ String url = getTileString(tileServer, x, y, z);
+ if (stamp != zoomStamp.longValue()) {
+ //System.err.println("pending load killed: " + url);
+ try {
+ // here is a race, we just live with.
+ if (!getDisplay().isDisposed()) {
+ getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ getCache().remove(tileServer, x, y, z);
+ }
+ });
+ }
+ } catch (SWTException e) {
+ log.log(Level.INFO, "swt exception during redraw display-race, ignoring");
+ }
+
+ return;
+ }
+ try {
+ //System.err.println("fetch " + url);
+ //Thread.sleep(2000);
+ InputStream in = new URL(url).openConnection().getInputStream();
+ imageData.set(new ImageData(in));
+ try {
+ // here is a race, we just live with.
+ if (!getDisplay().isDisposed()) {
+ getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ redraw();
+ }
+ });
+ }
+ } catch (SWTException e) {
+ log.log(Level.INFO, "swt exception during redraw display-race, ignoring");
+ }
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "failed to load imagedata from url: " + url, e);
+ }
+ }
+
+ public ImageData getImageData(Device device) {
+ return imageData.get();
+ }
+
+ public Image getImage(Display display) {
+ checkThread(display);
+ if (image == null && imageData.get() != null) {
+ image = new Image(display, imageData.get());
+ }
+ return image;
+ }
+
+ public void dispose(Display display) {
+ checkThread(display);
+ if (image != null) {
+ //System.err.println("disposing: " + getTileString(tileServer, x, y, z));
+ image.dispose();
+ }
+ }
+
+ private void checkThread(Display display) {
+ // jdk 1.6 bug from checkWidget still fails here
+ if (display.getThread() != Thread.currentThread()) {
+ throw new IllegalStateException("wrong thread to pick up the image");
+ }
+ }
+ }
+
+ private class MapMouseListener implements MouseListener, MouseWheelListener, MouseMoveListener, MouseTrackListener {
+ private Point mouseCoords = new Point(0, 0);
+ private Point downCoords;
+ private Point downPosition;
+
+ public void mouseEnter(MouseEvent e) {
+ GeoMap.this.forceFocus();
+ }
+
+ public void mouseExit(MouseEvent e) {
+ }
+
+ public void mouseHover(MouseEvent e) {
+ }
+
+ public void mouseDoubleClick(MouseEvent e) {
+ if (e.button == 1)
+ zoomIn(new Point(mouseCoords.x, mouseCoords.y));
+ else if (e.button == 3)
+ zoomOut(new Point(mouseCoords.x, mouseCoords.y));
+ }
+ public void mouseDown(MouseEvent e) {
+ if (e.button == 1 && (e.stateMask & SWT.CTRL) != 0) {
+ setCenterPosition(getCursorPosition());
+ redraw();
+ }
+ if (e.button == 1) {
+ downCoords = new Point(e.x, e.y);
+ downPosition = getMapPosition();
+ }
+ }
+ public void mouseUp(MouseEvent e) {
+ if (e.count == 1) {
+ handleDrag(e);
+ }
+ downCoords = null;
+ downPosition = null;
+ }
+
+ public void mouseMove(MouseEvent e) {
+ handlePosition(e);
+ handleDrag(e);
+ }
+ public void mouseScrolled(MouseEvent e) {
+ if (e.count == 1)
+ zoomIn(new Point(mouseCoords.x, mouseCoords.y));
+ else if (e.count == -1)
+ zoomOut(new Point(mouseCoords.x, mouseCoords.y));
+ }
+
+ private void handlePosition(MouseEvent e) {
+ mouseCoords = new Point(e.x, e.y);
+ }
+
+ private void handleDrag(MouseEvent e) {
+ if (downCoords != null) {
+ int tx = downCoords.x - e.x;
+ int ty = downCoords.y - e.y;
+ setMapPosition(downPosition.x + tx, downPosition.y + ty);
+ GeoMap.this.redraw();
+ }
+ }
+ }
+
+ //-------------------------------------------------------------------------
+ // tile url construction.
+ // change here to support some other tile
+
+ public static String getTileString(TileServer tileServer, int xtile, int ytile, int zoom) {
+ String number = ("" + zoom + "/" + xtile + "/" + ytile);
+ String url = tileServer.getURL() + number + ".png";
+ return url;
+ }
+
+ /* constants ... */
+ public static final TileServer[] TILESERVERS = {
+ new TileServer("http://tile.openstreetmap.org/", 18),
+ new TileServer("http://tah.openstreetmap.org/Tiles/tile/", 17),
+ };
+
+ public static final String NAMEFINDER_URL = "http://nominatim.openstreetmap.org/search";
+
+ public static final String ABOUT_MSG =
+ "MapWidget - Minimal Openstreetmap/Maptile Viewer\r\n" +
+ "Requirements: Java + SWT. Opensource and licensed under EPL.\r\n" +
+ "\r\n" +
+ "Web/Source: <a href=\"http://mappanel.sourceforge.net\">http://mappanel.sourceforge.net</a>\r\n" +
+ "Written by stepan.rutz. Contact <a href=\"mailto:stepan.rutz@gmx.de?subject=SWT%20MapWidget\">stepan.rutz@gmx.de</a>\r\n\r\n" +
+ "Tileserver and Namefinder are part of Openstreetmap.org or associated projects.\r\n";
+ //"MapPanel gets all its data the openstreetmap servers.\r\n\r\n" +
+ //"Please support the effort at <a href=\"http://www.openstreetmap.org\">http://www.openstreetmap.org/</a>.\r\n";
+ //"Please keep in mind this application is just a alternative renderer for swt.\r\n";
+
+
+ /* basically not be changed */
+ private static final int TILE_SIZE = 256;
+ public static final int CACHE_SIZE = 256;
+ public static final int IMAGEFETCHER_THREADS = 4;
+
+ private PropertyChangeSupport pcs = new PropertyChangeSupport(this);
+ private Point mapSize = new Point(0, 0);
+ private Point mapPosition = new Point(0, 0);
+ private int zoom;
+ private AtomicLong zoomStamp = new AtomicLong();
+
+ private TileServer tileServer = TILESERVERS[0];
+ private TileCache cache = new TileCache();
+ private Stats stats = new Stats();
+ private MapMouseListener mouseListener = new MapMouseListener();
+
+ private BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<Runnable>();
+ private ThreadFactory threadFactory = new ThreadFactory( ) {
+ public Thread newThread(Runnable r) {
+ Thread t = new Thread(r);
+ t.setName("Async Image Loader " + t.getId() + " " + System.identityHashCode(t));
+ t.setDaemon(true);
+ return t;
+ }
+ };
+ private ThreadPoolExecutor executor = new ThreadPoolExecutor(IMAGEFETCHER_THREADS, 16, 2, TimeUnit.SECONDS, workQueue, threadFactory);
+
+ private Color waitBackground, waitForeground;
+
+ public GeoMap(Composite parent, int style) {
+ this(parent, style, new Point(275091, 180145), 11);
+ }
+
+ public GeoMap(Composite parent, int style, Point mapPosition, int zoom) {
+ super(parent, SWT.DOUBLE_BUFFERED | style);
+ waitBackground = new Color(getDisplay(), 0x88, 0x88, 0x88);
+ waitForeground = new Color(getDisplay(), 0x77, 0x77, 0x77);
+
+ setZoom(zoom);
+ addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ GeoMap.this.widgetDisposed(e);
+ }
+ });
+ addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent e) {
+ GeoMap.this.paintControl(e);
+ }
+ });
+ setMapPosition(mapPosition);
+ addMouseListener(mouseListener);
+ addMouseMoveListener(mouseListener);
+ addMouseWheelListener(mouseListener);
+ addMouseTrackListener(mouseListener);
+ /// TODO: check tileservers
+ }
+
+ protected void paintControl(PaintEvent e) {
+ GC gc = e.gc;
+
+ getStats().reset();
+ long t0 = System.currentTimeMillis();
+ Point size = getSize();
+ int width = size.x, height = size.y;
+ int x0 = (int) Math.floor(((double) mapPosition.x) / TILE_SIZE);
+ int y0 = (int) Math.floor(((double) mapPosition.y) / TILE_SIZE);
+ int x1 = (int) Math.ceil(((double) mapPosition.x + width) / TILE_SIZE);
+ int y1 = (int) Math.ceil(((double) mapPosition.y + height) / TILE_SIZE);
+
+ int dy = y0 * TILE_SIZE - mapPosition.y;
+ for (int y = y0; y < y1; ++y) {
+ int dx = x0 * TILE_SIZE - mapPosition.x;
+ for (int x = x0; x < x1; ++x) {
+ paintTile(gc, dx, dy, x, y);
+ dx += TILE_SIZE;
+ ++getStats().tileCount;
+ }
+ dy += TILE_SIZE;
+ }
+
+ long t1 = System.currentTimeMillis();
+ stats.dt = t1 - t0;
+ //gc.drawString("dis ya draw", 20, 50);
+ }
+
+ private void paintTile(GC gc, int dx, int dy, int x, int y) {
+ Display display = getDisplay();
+ boolean DRAW_IMAGES = true;
+ boolean DEBUG = false;
+ boolean DRAW_OUT_OF_BOUNDS = !false;
+
+ boolean imageDrawn = false;
+ int xTileCount = 1 << zoom;
+ int yTileCount = 1 << zoom;
+ boolean tileInBounds = x >= 0 && x < xTileCount && y >= 0 && y < yTileCount;
+ boolean drawImage = DRAW_IMAGES && tileInBounds;
+ if (drawImage) {
+ TileCache cache = getCache();
+ TileServer tileServer = getTileServer();
+ AsyncImage image = cache.get(tileServer, x, y, zoom);
+ if (image == null) {
+ image = new AsyncImage(tileServer, x, y, zoom);
+ cache.put(tileServer, x, y, zoom, image);
+ }
+ if (image.getImage(getDisplay()) != null) {
+ gc.drawImage(image.getImage(getDisplay()), dx, dy);
+ imageDrawn = true;
+ }
+ }
+ if (DEBUG && (!imageDrawn && (tileInBounds || DRAW_OUT_OF_BOUNDS))) {
+ gc.setBackground(display.getSystemColor(tileInBounds ? SWT.COLOR_GREEN : SWT.COLOR_RED));
+ gc.fillRectangle(dx + 4, dy + 4, TILE_SIZE - 8, TILE_SIZE - 8);
+ gc.setForeground(display.getSystemColor(SWT.COLOR_BLACK));
+ String s = "T " + x + ", " + y + (!tileInBounds ? " #" : "");
+ gc.drawString(s, dx + 4+ 8, dy + 4 + 12);
+ } else if (!DEBUG && !imageDrawn && tileInBounds) {
+ gc.setBackground(waitBackground);
+ gc.fillRectangle(dx, dy, TILE_SIZE, TILE_SIZE);
+ gc.setForeground(waitForeground);
+ for (int yl = 0; yl < TILE_SIZE; yl += 32) {
+ gc.drawLine(dx, dy + yl, dx + TILE_SIZE, dy + yl);
+ }
+ for (int xl = 0; xl < TILE_SIZE; xl += 32) {
+ gc.drawLine(dx + xl, dy, dx + xl, dy + TILE_SIZE);
+ }
+ }
+ }
+
+ protected void widgetDisposed(DisposeEvent e) {
+ waitBackground.dispose();
+ waitForeground.dispose();
+ }
+
+ public void addPropertyChangeListener(PropertyChangeListener listener) {
+ pcs.addPropertyChangeListener(listener);
+ }
+
+ public void removePropertyChangeListener(PropertyChangeListener listener) {
+ pcs.removePropertyChangeListener(listener);
+ }
+
+ public void addPropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ pcs.addPropertyChangeListener(propertyName, listener);
+ }
+
+ public void removePropertyChangeListener(String propertyName, PropertyChangeListener listener) {
+ pcs.removePropertyChangeListener(propertyName, listener);
+ }
+
+ public TileCache getCache() {
+ return cache;
+ }
+
+ public TileServer getTileServer() {
+ return tileServer;
+ }
+
+ public void setTileServer(TileServer tileServer) {
+ this.tileServer = tileServer;
+ redraw();
+ }
+
+ public Stats getStats() {
+ return stats;
+ }
+
+ public Point getMapPosition() {
+ return new Point(mapPosition.x, mapPosition.y);
+ }
+
+ public void setMapPosition(Point mapPosition) {
+ setMapPosition(mapPosition.x, mapPosition.y);
+ }
+
+ public void setMapPosition(int x, int y) {
+ if (mapPosition.x == x && mapPosition.y == y)
+ return;
+ Point oldMapPosition = getMapPosition();
+ mapPosition.x = x;
+ mapPosition.y = y;
+ pcs.firePropertyChange("mapPosition", oldMapPosition, getMapPosition());
+ }
+
+
+
+ public void translateMapPosition(int tx, int ty) {
+ setMapPosition(mapPosition.x + tx, mapPosition.y + ty);
+ }
+
+ public int getZoom() {
+ return zoom;
+ }
+
+ public void setZoom(int zoom) {
+ if (zoom == this.zoom)
+ return;
+ zoomStamp.incrementAndGet();
+ int oldZoom = this.zoom;
+ this.zoom = Math.min(getTileServer().getMaxZoom(), zoom);
+ mapSize.x = getXMax();
+ mapSize.y = getYMax();
+ pcs.firePropertyChange("zoom", oldZoom, zoom);
+ }
+
+ public void zoomIn(Point pivot) {
+ if (getZoom() >= getTileServer().getMaxZoom())
+ return;
+ Point mapPosition = getMapPosition();
+ int dx = pivot.x;
+ int dy = pivot.y;
+ setZoom(getZoom() + 1);
+ setMapPosition(mapPosition.x * 2 + dx, mapPosition.y * 2 + dy);
+ redraw();
+ }
+
+ public void zoomOut(Point pivot) {
+ if (getZoom() <= 1)
+ return;
+ Point mapPosition = getMapPosition();
+ int dx = pivot.x;
+ int dy = pivot.y;
+ setZoom(getZoom() - 1);
+ setMapPosition((mapPosition.x - dx) / 2, (mapPosition.y - dy) / 2);
+ redraw();
+ }
+
+ public int getXTileCount() {
+ return (1 << zoom);
+ }
+
+ public int getYTileCount() {
+ return (1 << zoom);
+ }
+
+ public int getXMax() {
+ return TILE_SIZE * getXTileCount();
+ }
+
+ public int getYMax() {
+ return TILE_SIZE * getYTileCount();
+ }
+
+ public Point getCursorPosition() {
+ return new Point(mapPosition.x + mouseListener.mouseCoords.x, mapPosition.y + mouseListener.mouseCoords.y);
+ }
+
+ public Point getTile(Point position) {
+ return new Point((int) Math.floor(((double) position.x) / TILE_SIZE),(int) Math.floor(((double) position.y) / TILE_SIZE));
+ }
+
+ public Point getCenterPosition() {
+ org.eclipse.swt.graphics.Point size = getSize();
+ return new Point(mapPosition.x + size.x / 2, mapPosition.y + size.y / 2);
+ }
+
+ public void setCenterPosition(Point p) {
+ org.eclipse.swt.graphics.Point size = getSize();
+ setMapPosition(p.x - size.x / 2, p.y - size.y / 2);
+ }
+
+ public PointD getLongitudeLatitude(Point position) {
+ return new PointD(
+ position2lon(position.x, getZoom()),
+ position2lat(position.y, getZoom()));
+ }
+
+ public Point computePosition(PointD coords) {
+ int x = lon2position(coords.x, getZoom());
+ int y = lat2position(coords.y, getZoom());
+ return new Point(x, y);
+ }
+
+ //-------------------------------------------------------------------------
+ // utils
+ public static String format(double d) {
+ return String.format("%.5f", d);
+ }
+
+ public static double getN(int y, int z) {
+ double n = Math.PI - (2.0 * Math.PI * y) / Math.pow(2.0, z);
+ return n;
+ }
+
+ public static double position2lon(int x, int z) {
+ double xmax = TILE_SIZE * (1 << z);
+ return x / xmax * 360.0 - 180;
+ }
+
+ public static double position2lat(int y, int z) {
+ double ymax = TILE_SIZE * (1 << z);
+ return Math.toDegrees(Math.atan(Math.sinh(Math.PI - (2.0 * Math.PI * y) / ymax)));
+ }
+
+ public static double tile2lon(int x, int z) {
+ return x / Math.pow(2.0, z) * 360.0 - 180;
+ }
+
+ public static double tile2lat(int y, int z) {
+ return Math.toDegrees(Math.atan(Math.sinh(Math.PI - (2.0 * Math.PI * y) / Math.pow(2.0, z))));
+ }
+
+ public static int lon2position(double lon, int z) {
+ double xmax = TILE_SIZE * (1 << z);
+ return (int) Math.floor((lon + 180) / 360 * xmax);
+ }
+
+ public static int lat2position(double lat, int z) {
+ double ymax = TILE_SIZE * (1 << z);
+ return (int) Math.floor((1 - Math.log(Math.tan(Math.toRadians(lat)) + 1 / Math.cos(Math.toRadians(lat))) / Math.PI) / 2 * ymax);
+ }
+
+ public static String getTileNumber(TileServer tileServer, double lat, double lon, int zoom) {
+ int xtile = (int) Math.floor((lon + 180) / 360 * (1 << zoom));
+ int ytile = (int) Math.floor((1 - Math.log(Math.tan(Math.toRadians(lat)) + 1 / Math.cos(Math.toRadians(lat))) / Math.PI) / 2 * (1 << zoom));
+ return getTileString(tileServer, xtile, ytile, zoom);
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/GeoMapBrowser.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/GeoMapBrowser.java
new file mode 100644
index 0000000..56e3cb4
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/GeoMapBrowser.java
@@ -0,0 +1,119 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap;
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+
+import org.eclipse.nebula.widgets.geomap.internal.InfoPage;
+import org.eclipse.nebula.widgets.geomap.internal.PageContainer;
+import org.eclipse.nebula.widgets.geomap.internal.ResultsPage;
+import org.eclipse.nebula.widgets.geomap.internal.SearchPage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.SashForm;
+import org.eclipse.swt.events.ControlAdapter;
+import org.eclipse.swt.events.ControlEvent;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.MouseMoveListener;
+import org.eclipse.swt.layout.FillLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Display;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Menu;
+import org.eclipse.swt.widgets.MenuItem;
+import org.eclipse.swt.widgets.Shell;
+
+/**
+ * @author stepan.rutz@gmx.de
+ * @version $Revision$
+ */
+public class GeoMapBrowser extends Composite {
+ private SashForm sashForm;
+ private PageContainer pageContainer;
+ private GeoMap mapWidget;
+ private SearchPage searchPage;
+ private ResultsPage resultsPage;
+ private InfoPage infoPage;
+
+ public GeoMapBrowser(Composite parent, int style) {
+ super(parent, style);
+
+ setLayout(new FillLayout());
+
+ sashForm = new SashForm(this, SWT.HORIZONTAL);
+ sashForm.setLayout(new FillLayout());
+
+ pageContainer = new PageContainer(sashForm, SWT.NONE);
+ mapWidget = new GeoMap(sashForm, SWT.NONE);
+
+ sashForm.setWeights(new int[] { 100, 200 });
+
+ searchPage = new SearchPage(this);
+ resultsPage = new ResultsPage(this);
+ infoPage = new InfoPage(this);
+ pageContainer.setPages(searchPage, resultsPage, infoPage);
+ pageContainer.showPage(0);
+
+ mapWidget.addPropertyChangeListener(new PropertyChangeListener() {
+ public void propertyChange(PropertyChangeEvent event) {
+ infoPage.updateInfos();
+ }
+ });
+ mapWidget.addControlListener(new ControlAdapter() {
+ public void controlResized(ControlEvent e) {
+ infoPage.updateInfos();
+ }
+ });
+ mapWidget.addMouseMoveListener(new MouseMoveListener() {
+ public void mouseMove(MouseEvent e) {
+ infoPage.updateInfos();
+ }
+ });
+ }
+
+ public GeoMap getMapWidget() {
+ return mapWidget;
+ }
+
+ public SearchPage getSearchPage() {
+ return searchPage;
+ }
+
+ public InfoPage getInfoPage() {
+ return infoPage;
+ }
+
+ public ResultsPage getResultsPage() {
+ return resultsPage;
+ }
+
+ public PageContainer getPageContainer() {
+ return pageContainer;
+ }
+
+ private void createMenu(Shell shell) {
+ Menu bar = new Menu (shell, SWT.BAR);
+ shell.setMenuBar (bar);
+ MenuItem fileItem = new MenuItem (bar, SWT.CASCADE);
+ fileItem.setText ("&File");
+ Menu submenu = new Menu (shell, SWT.DROP_DOWN);
+ fileItem.setMenu (submenu);
+ MenuItem item = new MenuItem (submenu, SWT.PUSH);
+ item.addListener (SWT.Selection, new Listener () {
+ public void handleEvent (Event e) {
+ Runtime.getRuntime().halt(0);
+ }
+ });
+ item.setText ("E&xit\tCtrl+W");
+ item.setAccelerator(SWT.MOD1 + 'W');
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/PointD.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/PointD.java
new file mode 100644
index 0000000..3ac54f9
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/PointD.java
@@ -0,0 +1,38 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap;
+
+/**
+ * Holds x and y coordinates of type double.
+ */
+public final class PointD {
+
+ /**
+ * The x coordinate
+ */
+ public double x;
+
+ /**
+ * The y coordinate
+ */
+ public double y;
+
+ /**
+ * Initializes this PointD with the provided x- and y-coordinates
+ * @param x the x coordinate
+ * @param y the y coordinate
+ */
+ public PointD(double x, double y) {
+ this.x = x;
+ this.y = y;
+ }
+} \ No newline at end of file
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/AbstractPage.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/AbstractPage.java
new file mode 100644
index 0000000..a6ecfcd
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/AbstractPage.java
@@ -0,0 +1,132 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap.internal;
+import org.eclipse.nebula.widgets.geomap.GeoMap;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.program.Program;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Listener;
+
+/**
+ * Base implementation of an abstract page, eg something that owns an swt
+ * control. Common functions are a header widget and an embedded
+ * {@link PageContainer}.
+ *
+ * <p>This file is part of the showcase for the {@link GeoMap} but does
+ * not include any core functionality that is typically embedded. Users who
+ * only want to embed the swt-map as a widget don't typically use this class.
+ * </p>
+ *
+ * @author stepan.rutz@gmx.de
+ * @version $Revision$
+ */
+public abstract class AbstractPage implements Page {
+
+ private PageContainer container;
+ private Composite composite;
+ private Image actionImage;
+
+
+ protected PageContainer getContainer() {
+ return container;
+ }
+
+ protected Composite getComposite() {
+ return composite;
+ }
+
+ public Control getControl(PageContainer container, Composite parent) {
+ if (composite == null) {
+ this.container = container;
+ composite = new Composite(parent, SWT.NONE);
+ composite.addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ AbstractPage.this.widgetDisposed(e);
+ }
+ });
+ actionImage = new Image(composite.getDisplay(), getClass().getResourceAsStream("resources/action.gif"));
+
+ composite.setLayout(new GridLayout(2, false));
+ container.adapt(composite);
+
+
+ initContent(container, composite);
+ }
+ return composite;
+ }
+
+ protected void addHeaderRow(PageContainer container, Composite parent, String text) {
+ HeaderControl header = new HeaderControl(parent);
+ container.adapt(header);
+ header.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false, 2 , 1));
+ header.setText(text);
+ }
+
+ protected Link addInfoText(PageContainer container, Composite parent, String text) {
+ Link link = new Link(parent, SWT.WRAP | SWT.MULTI);
+ container.adapt(link);
+ GridData layoutData = new GridData(GridData.FILL, GridData.BEGINNING, true, false, 2 , 1);
+ link.setLayoutData(layoutData);
+ link.setText(text);
+ link.addListener (SWT.Selection, new Listener () {
+ public void handleEvent(Event event) {
+ try {
+ if (event.text != null && event.text.length() > 0)
+ Program.launch(event.text);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+
+ return link;
+ }
+
+
+ protected void addActionLink(PageContainer container, Composite parent, String text, SelectionAdapter selectionAdapter) {
+ Composite wrap = new Composite(parent, SWT.NONE);
+ wrap.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1));
+ container.adapt(wrap);
+
+ GridLayout layout = new GridLayout(2, false);
+ layout.marginLeft = 8;
+ layout.marginHeight = 0;
+ wrap.setLayout(layout);
+
+ Label titleImage = new Label(wrap, SWT.WRAP);
+ container.adapt(titleImage);
+ titleImage.setImage(actionImage);
+ Link link = new Link(wrap, SWT.NONE);
+ container.adapt(link);
+ link.setText(text);
+ link.addSelectionListener(selectionAdapter);
+ }
+
+ protected abstract void widgetDisposed(DisposeEvent e);
+
+ protected abstract void initContent(PageContainer container, Composite composite);
+
+
+
+}
+
+
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/HeaderControl.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/HeaderControl.java
new file mode 100644
index 0000000..61a9d87
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/HeaderControl.java
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap.internal;
+
+import org.eclipse.nebula.widgets.geomap.GeoMap;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * A simple custom-drawn swt control that renders a header (eg some
+ * type of prominent label.
+ *
+ * <p>This file is part of the showcase for the {@link GeoMap} but does
+ * not include any core functionality that is typically embedded. Users who
+ * only want to embed the swt-map as a widget don't typically use this class.
+ * </p>
+ *
+ * @author stepan.rutz
+ * @version $Revision$
+ */
+public class HeaderControl extends Canvas {
+
+ private static final int TOP_SPACE = 6;
+ private Font font;
+ private Color foreground;
+ private String text = "";
+ private Point size = new Point(1, 1);
+
+ public HeaderControl(Composite parent) {
+ super(parent, SWT.DOUBLE_BUFFERED);
+ addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent e) {
+ onPaint(e);
+ }
+ });
+ addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ onDispose(e);
+ }
+ });
+
+ font = new Font(getDisplay(), "Tahoma", 10, SWT.BOLD);
+ foreground = new Color(getDisplay(), 87, 166, 212);
+ measureString("M");
+ }
+
+ private void measureString(String s) {
+ GC gc = new GC(this);
+ try {
+ gc.setFont(font);
+ size = gc.stringExtent(s);
+ size.y += TOP_SPACE;
+ } finally {
+ gc.dispose();
+ }
+ }
+
+ private void onDispose(DisposeEvent e) {
+ font.dispose();
+ foreground.dispose();
+ }
+
+ private void onPaint(PaintEvent e) {
+ GC gc = e.gc;
+ gc.setFont(font);
+ gc.setForeground(foreground);
+ gc.drawString(text, 0, TOP_SPACE, true);
+ Point size = getSize();
+ int w = size.x;
+ int h = size.y;
+ gc.drawLine(0, h - 1, w, h - 1);
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ /**
+ * Sets the texts and recomputes the size of the receiver. Finally a
+ * redraw is scheduled.
+ * @param text
+ */
+ public void setText(String text) {
+ this.text = text;
+ measureString(text);
+ redraw();
+ }
+
+ @Override
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ return new Point(size.x, size.y);
+ }
+
+
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/InfoPage.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/InfoPage.java
new file mode 100644
index 0000000..9912a7f
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/InfoPage.java
@@ -0,0 +1,136 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap.internal;
+import java.text.NumberFormat;
+import java.util.logging.Logger;
+
+import org.eclipse.nebula.widgets.geomap.GeoMap;
+import org.eclipse.nebula.widgets.geomap.GeoMapBrowser;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+/**
+ * @author stepan.rutz@gmx.de
+ * @version $Revision$
+ */
+public class InfoPage extends AbstractPage implements Page {
+
+ private static final Logger log = Logger.getLogger(InfoPage.class.getName());
+
+ private abstract class Spec {
+ final String key;
+ final GeoMap mapWidget;
+ abstract String computeValue();
+ Spec(String key) { this.key = key; this.mapWidget = mapBrowser.getMapWidget(); }
+ }
+
+
+ private final GeoMapBrowser mapBrowser;
+ private Table table;
+ private Spec[] specs;
+
+ public InfoPage(GeoMapBrowser mapBrowser) {
+ this.mapBrowser = mapBrowser;
+ specs = new Spec[] {
+ new Spec("Zoom") { public String computeValue() { return Integer.toString(mapWidget.getZoom()); }},
+ new Spec("Map Size") { public String computeValue() { Point size = mapWidget.getSize(); return size.x + ", " + size.y; }},
+ new Spec("Map Position") { public String computeValue() { Point position = mapWidget.getMapPosition(); return position.x + ", " + position.y; }},
+ new Spec("Center Position") { public String computeValue() { Point position = mapWidget.getCenterPosition(); return position.x + ", " + position.y; }},
+ new Spec("Paint time") { public String computeValue() { mapWidget.getStats(); return mapWidget.getStats().dt + " ms"; }},
+ new Spec("Imagefetchers Threads") { public String computeValue() { return Integer.toString(GeoMap.IMAGEFETCHER_THREADS); }},
+ new Spec("Number painted tiles") {
+ public String computeValue() {
+ mapWidget.getStats();
+ return mapWidget.getStats().tileCount + " of " + NumberFormat.getIntegerInstance().format((long)mapWidget.getXTileCount() * mapWidget.getYTileCount());
+ }
+ },
+ new Spec("Tilecache") { public String computeValue() { return String.format("%3d / %3d", mapWidget.getCache().getSize(), GeoMap.CACHE_SIZE); }},
+ new Spec("Longitude/Latitude") {
+ public String computeValue() {
+ Point p = mapWidget.getCursorPosition();
+ int zoom = mapWidget.getZoom();
+ return GeoMap.format(GeoMap.position2lon(p.x, zoom)) + ", " + GeoMap.format(GeoMap.position2lat(p.y, zoom));
+ }
+ },
+
+ };
+ }
+
+ public void updateInfos() {
+ if (table == null)
+ return;
+ for (int i = 0; i < specs.length; ++i) {
+ Spec spec = specs[i];
+ TableItem item = table.getItem(i);
+ item.setText(1, spec.computeValue());
+ }
+ }
+
+
+ protected void initContent(final PageContainer container, Composite composite) {
+ addHeaderRow(container, composite, "Actions");
+ addActionLink(container, composite, "<a>Back to main menu</a>", new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ container.showPage(0);
+ }
+ });
+
+ addHeaderRow(container, composite, "Infos");
+ addInfoText(container, composite, "The following search results were retrieved from openstreetmap.org. " +
+ "Double-click to open a location.");
+
+ table = new Table(composite, SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+ table.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2 , 1));
+
+ table.setHeaderVisible(true);
+ table.setLinesVisible(true);
+ TableColumn column1 = new TableColumn(table, SWT.NONE);
+ column1.setText("Place");
+ column1.setWidth(120);
+ TableColumn column2 = new TableColumn(table, SWT.NONE);
+ column2.setText("Place");
+ column2.setWidth(160);
+
+ for (Spec spec : specs) {
+ TableItem item = new TableItem(table, SWT.NONE);
+ item.setText(0, spec.key);
+ }
+
+ addHeaderRow(container, composite, "Authors Remarks");
+ addInfoText(container, composite,
+ "The number of image fetcher threads determines how many background tasks are " +
+ "run simultaneously to fetch tiles. The search is also performed in the background. " +
+ "The tilecache fill never drops below its maximum size once its filled, but the eldest " +
+ "entries are discarded on a LRU (Least-Recently-Used) basis.");
+ addInfoText(container, composite,
+ "The MapWidget can be used without all of this quite useless showcase application. Its " +
+ "main purpose is to showcase the MapWidget.");
+
+ addHeaderRow(container, composite, "Quick Help");
+ addInfoText(container, composite, "Use the mouse wheel to zoom in and zoom out. Drag the mouse to change " +
+ "your position on the map");
+ updateInfos();
+ }
+
+ protected void widgetDisposed(DisposeEvent e) {
+ }
+
+
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/Page.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/Page.java
new file mode 100644
index 0000000..bef4a75
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/Page.java
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap.internal;
+
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * @author stepan.rutz
+ * @version $Revision$
+ */
+public interface Page {
+ Control getControl(PageContainer container, Composite parent);
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/PageContainer.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/PageContainer.java
new file mode 100644
index 0000000..e98003e
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/PageContainer.java
@@ -0,0 +1,98 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+
+package org.eclipse.nebula.widgets.geomap.internal;
+import java.util.ArrayList;
+import java.util.Arrays;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.StackLayout;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+
+/**
+ * An <code>Composite</code> subclass that shows just one
+ * of its child pages at a time.
+ *
+ * @see Page
+ *
+ * @author stepan.rutz@gmx.de
+ * @version $Revision$
+ */
+public class PageContainer extends Composite {
+
+ private Composite content;
+ private StackLayout stackLayout;
+ private ArrayList<Page> pages = new ArrayList<Page>();
+ private int activePageIndex = -1;
+
+ public PageContainer(Composite parent, int style) {
+ super(parent, style);
+ addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ PageContainer.this.widgetDisposed(e);
+ }
+ });
+ adapt(this);
+ GridLayout layout = new GridLayout(1, false);
+ layout.marginWidth = layout.marginHeight = 0;
+ setLayout(layout);
+
+ stackLayout = new StackLayout();
+
+ TitleControl title = new TitleControl(this);
+ adapt(title);
+ title.setLayoutData(new GridData(GridData.FILL, GridData.BEGINNING, true, false));
+ title.setText("SWT MapWidget");
+
+ content = new Composite(this, SWT.NONE);
+ content.setLayout(stackLayout);
+ content.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
+ adapt(content);
+ }
+
+ protected void widgetDisposed(DisposeEvent e) {
+ }
+
+ public void setPages(Page... pages) {
+ this.pages.clear();
+ this.pages.addAll(Arrays.asList(pages));
+ }
+
+ public Page[] getPages() {
+ return pages.toArray(new Page[pages.size()]);
+ }
+
+ public int indexOfPage(Page page) {
+ return pages.indexOf(page);
+ }
+
+ public int getActivePageIndex() {
+ return activePageIndex;
+ }
+
+ public void showPage(int index) {
+ stackLayout.topControl = pages.get(index).getControl(this, content);
+ content.layout();
+ activePageIndex = index;
+ }
+
+ public void adapt(Control control) {
+ control.setBackground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
+ }
+}
+
+
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/ResultsPage.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/ResultsPage.java
new file mode 100644
index 0000000..cc6f6b0
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/ResultsPage.java
@@ -0,0 +1,155 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap.internal;
+import java.util.logging.Logger;
+
+import org.eclipse.nebula.widgets.geomap.GeoMap;
+import org.eclipse.nebula.widgets.geomap.GeoMapBrowser;
+import org.eclipse.nebula.widgets.geomap.PointD;
+import org.eclipse.nebula.widgets.geomap.internal.SearchPage.SearchResult;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.custom.ScrolledComposite;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.MouseAdapter;
+import org.eclipse.swt.events.MouseEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Event;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Listener;
+import org.eclipse.swt.widgets.Table;
+import org.eclipse.swt.widgets.TableColumn;
+import org.eclipse.swt.widgets.TableItem;
+
+
+/**
+ * @author stepan.rutz@gmx.de
+ * @version $Revision$
+ */
+public class ResultsPage extends AbstractPage implements Page {
+
+ private static final Logger log = Logger.getLogger(ResultsPage.class.getName());
+
+ private final GeoMapBrowser mapBrowser;
+ private Table table;
+
+ private String search = "";
+ private SearchResult[] results = new SearchResult[0];
+
+ private ScrolledComposite sc;
+
+ private Link descriptionText;
+
+
+ public ResultsPage(GeoMapBrowser mapBrowser) {
+ this.mapBrowser = mapBrowser;
+ }
+
+ public String getSearch() {
+ return search;
+ }
+
+ public void setSearch(String search) {
+ this.search = search;
+ }
+
+ public SearchResult[] getResults() {
+ return results.clone();
+ }
+
+ public void setResults(SearchResult[] results) {
+ this.results = results.clone();
+ table.removeAll();
+ for (SearchResult result : results) {
+
+ String shortName = result.getName();
+ shortName = shortName.replaceAll("\\s(.*)$", "");
+ String linkBody = shortName + " [" + result.getCategory() + "]";
+
+ String description = result.getDescription();
+ description = description.replaceAll("\\[.*?\\]", "");
+
+ TableItem item = new TableItem(table, SWT.NONE);
+ item.setText(0, linkBody);
+ }
+ }
+
+ protected void initContent(final PageContainer container, Composite composite) {
+ addHeaderRow(container, composite, "Actions");
+ addActionLink(container, composite, "<a>Back to main menu</a>", new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ container.showPage(0);
+ }
+ });
+
+ addHeaderRow(container, composite, "Results");
+ addInfoText(container, composite, "The following search results were retrieved from openstreetmap.org. " +
+ "Double-click to open a location.");
+
+ table = new Table(composite, SWT.FULL_SELECTION | SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER);
+ table.setLayoutData(new GridData(GridData.FILL, GridData.FILL, true, true, 2 , 1));
+
+ table.setHeaderVisible(!true);
+ table.setLinesVisible(true);
+ TableColumn column1 = new TableColumn(table, SWT.NONE);
+ column1.setText("Place");
+ column1.setWidth(260);
+
+ addHeaderRow(container, composite, "Description");
+ descriptionText = addInfoText(container, composite, "");
+ GridData layoutData = (GridData) descriptionText.getLayoutData();
+ layoutData.minimumHeight = 100;
+ layoutData.grabExcessVerticalSpace = false;
+ layoutData.heightHint = 160;
+
+ table.addListener (SWT.Selection, new Listener () {
+ public void handleEvent (Event event) {
+ if (event.detail == SWT.CHECK)
+ return;
+ TableItem item = (TableItem) event.item;
+ int index = table.indexOf(item);
+ if (index >= 0 && index < results.length) {
+ SearchResult result = results[index];
+ String description = result.getDescription();
+ description = description.replaceAll("\\[.*?\\]", "");
+ description = description.replaceAll("<.*?>", "");
+ descriptionText.setText(description);
+ descriptionText.getParent().layout();
+ }
+ }
+ });
+
+ table.addMouseListener(new MouseAdapter() {
+ public void mouseDoubleClick(MouseEvent e) {
+ Point point = new Point(e.x, e.y);
+ TableItem item = table.getItem(point);
+ if (item == null)
+ return;
+ int index = table.indexOf(item);
+ if (index >= 0 && index < results.length) {
+ SearchResult result = results[index];
+ GeoMap mapWidget = mapBrowser.getMapWidget();
+ mapWidget.setZoom(result.getZoom() < 1 || result.getZoom() > mapWidget.getTileServer().getMaxZoom() ? 8 : result.getZoom());
+ Point position = mapWidget.computePosition(new PointD(result.getLon(), result.getLat()));
+ mapWidget.setCenterPosition(position);
+ mapWidget.redraw();
+ }
+ }
+ });
+ }
+
+ protected void widgetDisposed(DisposeEvent e) {
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/SearchPage.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/SearchPage.java
new file mode 100644
index 0000000..71cbd3e
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/SearchPage.java
@@ -0,0 +1,329 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap.internal;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.xml.parsers.SAXParserFactory;
+
+import org.eclipse.nebula.widgets.geomap.GeoMap;
+import org.eclipse.nebula.widgets.geomap.GeoMapBrowser;
+import org.eclipse.nebula.widgets.geomap.PointD;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.ProgressBar;
+import org.eclipse.swt.widgets.Text;
+import org.xml.sax.Attributes;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.DefaultHandler;
+
+
+/**
+ * A {link {@link Page} that allows searching use the OSM namefinder facility.
+ * The OSM namefinder has its own usage policies. Please check them out before
+ * you use it.
+ *
+ * @author stepan.rutz@gmx.de
+ * @version $Revision$
+ */
+public class SearchPage extends AbstractPage implements Page {
+
+ private static final Logger log = Logger.getLogger(SearchPage.class.getName());
+
+ public static final class SearchResult {
+ private String type;
+ private double lat, lon;
+ private String name;
+ private String category;
+ private String info;
+ private int zoom;
+ private String description = "";
+
+ public SearchResult() {
+ }
+ public String getType() {
+ return type;
+ }
+ public void setType(String type) {
+ this.type = type;
+ }
+ public double getLat() {
+ return lat;
+ }
+ public void setLat(double lat) {
+ this.lat = lat;
+ }
+ public double getLon() {
+ return lon;
+ }
+ public void setLon(double lon) {
+ this.lon = lon;
+ }
+ public String getName() {
+ return name;
+ }
+ public void setName(String name) {
+ this.name = name;
+ }
+ public String getCategory() {
+ return category;
+ }
+ public void setCategory(String category) {
+ this.category = category;
+ }
+ public String getInfo() {
+ return info;
+ }
+ public void setInfo(String info) {
+ this.info = info;
+ }
+ public int getZoom() {
+ return zoom;
+ }
+ public void setZoom(int zoom) {
+ this.zoom = zoom;
+ }
+ public String getDescription() {
+ return description;
+ }
+ public void setDescription(String description) {
+ this.description = description;
+ }
+ public String toString() {
+ return "SearchResult [category=" + category + ", info=" + info + ", lat=" + lat + ", lon=" + lon
+ + ", name=" + name + ", type=" + type + ", zoom=" + zoom + ", description=" + description + "]";
+ }
+
+ }
+
+ private final GeoMapBrowser mapBrowser;
+ private ProgressBar progressBar;
+ private GridData progressBarLayoutData;
+ private Text searchText;
+ private boolean searching;
+
+ private ArrayList<SearchResult> results = new ArrayList<SearchResult>();
+ private Link searchLink;
+
+ public SearchPage(GeoMapBrowser mapBrowser) {
+ this.mapBrowser = mapBrowser;
+ }
+
+ protected void initContent(final PageContainer container, Composite composite) {
+ addHeaderRow(container, composite, "Infopanel");
+ addInfoText(container, composite, "Toggling the tile-server changes the way " +
+ "the map is rendered. Click on the mapinfos link to see details " +
+ "about the currently rendered part of the map.");
+
+ addActionLink(container, composite, "<a>Toggle Rendering</a>", new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ GeoMap mapWidget = mapBrowser.getMapWidget();
+ int next = (Arrays.asList(GeoMap.TILESERVERS).indexOf(mapWidget.getTileServer()) + 1) % GeoMap.TILESERVERS.length;
+ mapWidget.setTileServer(GeoMap.TILESERVERS[next]);
+ }
+ });
+
+ addActionLink(container, composite, "Show <a>Technical Mapinfos</a>", new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ mapBrowser.getPageContainer().showPage(mapBrowser.getPageContainer().indexOfPage(mapBrowser.getInfoPage()));
+ }
+ });
+ addActionLink(container, composite, "Show <a>Europe</a>", new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ GeoMap mapWidget = mapBrowser.getMapWidget();
+ mapWidget.setZoom(5);
+ Point position = mapWidget.computePosition(new PointD(5.5, 52.2));
+ mapWidget.setCenterPosition(position);
+ mapWidget.redraw();
+ }
+ });
+
+ addHeaderRow(container, composite, "Search location");
+ addInfoText(container, composite, "Enter any location or landmark site to search openstreetmap's " +
+ "genuine namefinder database. Hit return to perform the search.");
+
+ {
+ Label label = new Label(composite, SWT.NONE);
+ label.setText("Search:");
+ label.setLayoutData(new GridData());
+ container.adapt(label);
+ }
+ {
+ Composite wrap = new Composite(composite, SWT.NONE);
+ wrap.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ container.adapt(wrap);
+
+ GridLayout layout = new GridLayout(2, false);
+ //layout.marginLeft = 8;
+ //layout.marginHeight = 0;
+ wrap.setLayout(layout);
+
+ searchText = new Text(wrap, SWT.BORDER | SWT.SEARCH);
+ searchText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
+ searchText.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ startSearch();
+ }
+ public void widgetDefaultSelected(SelectionEvent e) {
+ startSearch();
+ }
+ });
+ searchLink = new Link(wrap, SWT.NONE);
+ searchLink.setText("<a>Go</a>");
+ container.adapt(searchLink);
+ searchLink.addSelectionListener(new SelectionAdapter() {
+ public void widgetSelected(SelectionEvent e) {
+ startSearch();
+ }
+ });
+ }
+
+ progressBar = new ProgressBar(composite, SWT.SMOOTH | SWT.INDETERMINATE);
+ container.adapt(progressBar);
+ progressBarLayoutData = new GridData(GridData.FILL, GridData.BEGINNING, true, false, 2 , 1);
+ progressBarLayoutData.exclude = true;
+ progressBar.setVisible(false);
+ progressBar.setLayoutData(progressBarLayoutData);
+
+ addHeaderRow(container, composite, "Actions");
+ addInfoText(container, composite, GeoMap.ABOUT_MSG);
+ }
+
+ protected void widgetDisposed(DisposeEvent e) {
+ }
+
+ public void startSearch() {
+ if (searching)
+ return;
+ final String search = searchText.getText();
+ if (search == null || search.length() == 0)
+ return;
+
+ searching = true;
+ setupSearchGui();
+ Thread t = new Thread(new Runnable() {
+ public void run() {
+ doSearchInternal(search);
+ }
+ });
+ t.setName("Background Seacher \"" + search + "\"");
+ t.start();
+ }
+
+ private void setupSearchGui() {
+ progressBarLayoutData.exclude = false;
+ progressBar.setVisible(true);
+ searchText.setEnabled(false);
+ searchLink.setEnabled(false);
+ progressBar.getParent().layout();
+ }
+
+ private void tearDownSearchGui() {
+ progressBarLayoutData.exclude = true;
+ progressBar.setVisible(false);
+ searchText.setEnabled(true);
+ searchLink.setEnabled(true);
+ progressBar.getParent().layout();
+ }
+
+ private void doSearchInternal(final String newSearch) {
+ results.clear();
+ try {
+ String args = URLEncoder.encode(newSearch, "UTF-8");
+ String path = GeoMap.NAMEFINDER_URL + "?format=xml&q=" + args;
+ SAXParserFactory factory = SAXParserFactory.newInstance();
+ factory.setValidating(false);
+ factory.newSAXParser().parse(path, new DefaultHandler() {
+ private final ArrayList<String> pathStack = new ArrayList<String>();
+// private final ArrayList<SearchResult> namedStack = new ArrayList<SearchResult>();
+ private StringBuilder chars;
+ public void startElement(String uri, String localName, String qName, Attributes attributes) {
+ pathStack.add(qName);
+ String path = getPath();
+ if ("place".equals(qName)) {
+ SearchResult result = new SearchResult();
+ result.setType(attributes.getValue("type"));
+ result.setLat(tryDouble(attributes.getValue("lat")));
+ result.setLon(tryDouble(attributes.getValue("lon")));
+ result.setName(attributes.getValue("display_name"));
+ result.setCategory(attributes.getValue("category"));
+ result.setInfo(attributes.getValue("info"));
+ result.setZoom(tryInteger(attributes.getValue("zoom")));
+// namedStack.add(result);
+ if (pathStack.size() == 2)
+ results.add(result);
+// } else if ("description".equals(qName)) {
+// chars = new StringBuilder();
+ }
+ }
+ public void endElement(String uri, String localName, String qName) throws SAXException {
+// if ("place".equals(qName)) {
+// pathStack.remove(pathStack.size() - 1);
+// } else if ("description".equals(qName)) {
+// namedStack.get(namedStack.size() - 1).setDescription(chars.toString());
+// }
+ pathStack.remove(pathStack.size() - 1);
+ }
+ public void characters(char[] ch, int start, int length) throws SAXException {
+ if(chars != null)
+ chars.append(ch, start, length);
+ }
+ private String getPath() {
+ StringBuilder sb = new StringBuilder();
+ for (String p : pathStack)
+ sb.append("/").append(p);
+ return sb.toString();
+ }
+ private double tryDouble(String s) {
+ try {
+ return Double.valueOf(s);
+ } catch (Exception e) {
+ return 0d;
+ }
+ }
+ private int tryInteger(String s) {
+ try {
+ return Integer.valueOf(s);
+ } catch (Exception e) {
+ return 0;
+ }
+ }
+ });
+ } catch (Exception e) {
+ log.log(Level.SEVERE, "failed to search for \"" + newSearch + "\"", e);
+ }
+ getComposite().getDisplay().asyncExec(new Runnable() {
+ public void run() {
+ try {
+ ResultsPage resultsPage = mapBrowser.getResultsPage();
+ resultsPage.setSearch(newSearch);
+ mapBrowser.getPageContainer().showPage(mapBrowser.getPageContainer().indexOfPage(resultsPage));
+ resultsPage.setResults(results.toArray(new SearchResult[results.size()]));
+ } finally {
+ searching = false;
+ tearDownSearchGui();
+ }
+ }
+ });
+ }
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/TitleControl.java b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/TitleControl.java
new file mode 100644
index 0000000..27927f9
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/TitleControl.java
@@ -0,0 +1,128 @@
+/*******************************************************************************
+ * Copyright (c) 2008, 2012 Stepan Rutz.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Stepan Rutz - initial implementation
+ *******************************************************************************/
+
+package org.eclipse.nebula.widgets.geomap.internal;
+
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.DisposeEvent;
+import org.eclipse.swt.events.DisposeListener;
+import org.eclipse.swt.events.PaintEvent;
+import org.eclipse.swt.events.PaintListener;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.Font;
+import org.eclipse.swt.graphics.GC;
+import org.eclipse.swt.graphics.Image;
+import org.eclipse.swt.graphics.Point;
+import org.eclipse.swt.graphics.Rectangle;
+import org.eclipse.swt.widgets.Canvas;
+import org.eclipse.swt.widgets.Composite;
+
+/**
+ * An owner-drawn title label type of swt-control.
+ *
+ * @author stepan.rutz
+ * @version $Revision$
+ */
+public class TitleControl extends Canvas {
+
+ private static final int TOP_SPACE = 0;
+ private Font font;
+ private Color gradient1Color;
+ private Color gradient2Color;
+ private Color bottomLineColor;
+ private Color writingColor;
+ private Image image;
+ private String text = "";
+ private Point size = new Point(1, 1);
+
+ public TitleControl(Composite parent) {
+ super(parent, SWT.DOUBLE_BUFFERED);
+ addPaintListener(new PaintListener() {
+ public void paintControl(PaintEvent e) {
+ onPaint(e);
+ }
+ });
+ addDisposeListener(new DisposeListener() {
+ public void widgetDisposed(DisposeEvent e) {
+ onDispose(e);
+ }
+ });
+
+ font = new Font(getDisplay(), "Tahoma", 10, SWT.BOLD);
+ gradient1Color = new Color(getDisplay(), 255, 255, 255);
+ gradient2Color = new Color(getDisplay(), 205, 224, 244);
+ bottomLineColor = new Color(getDisplay(), 200, 195, 216);
+ writingColor = new Color(getDisplay(), 60, 60, 60);
+ image = new Image(getDisplay(), getClass().getResourceAsStream("resources/world.png"));
+ measureSize("M");
+ }
+
+ private void measureSize(String s) {
+ GC gc = new GC(this);
+ try {
+ gc.setFont(font);
+ size = gc.stringExtent(s);
+ size.y = Math.max(image.getBounds().height + 1, size.y);
+ size.y += TOP_SPACE;
+ } finally {
+ gc.dispose();
+ }
+ }
+
+ private void onDispose(DisposeEvent e) {
+ font.dispose();
+ gradient1Color.dispose();
+ gradient2Color.dispose();
+ bottomLineColor.dispose();
+ writingColor.dispose();
+ image.dispose();
+ }
+
+ private void onPaint(PaintEvent e) {
+ GC gc = e.gc;
+ Point s = getSize();
+ int w = s.x;
+ int h = s.y;
+
+ gc.setForeground(gradient1Color);
+ gc.setBackground(gradient2Color);
+ gc.fillGradientRectangle(0, 0, w, h - 1, true);
+
+
+ Rectangle imgsize = image.getBounds();
+ gc.drawImage(image, 12, 0);
+ gc.setForeground(bottomLineColor);
+ gc.drawLine(0, h - 1, w, h - 1);
+
+ gc.setFont(font);
+ gc.setForeground(writingColor);
+ Point textSize = gc.stringExtent(text);
+ int ty = (h - textSize.y) / 2;
+ gc.drawString(text, 22 + imgsize.width, TOP_SPACE + ty, true);
+ }
+
+ public String getText() {
+ return text;
+ }
+
+ public void setText(String text) {
+ this.text = text;
+ measureSize(text);
+ redraw();
+ }
+
+ @Override
+ public Point computeSize(int wHint, int hHint, boolean changed) {
+ return new Point(size.x, size.y);
+ }
+
+
+}
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/resources/action.gif b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/resources/action.gif
new file mode 100644
index 0000000..e3a7cc7
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/resources/action.gif
Binary files differ
diff --git a/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/resources/world.png b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/resources/world.png
new file mode 100644
index 0000000..269e7ef
--- /dev/null
+++ b/widgets/geomap/org.eclipse.nebula.widgets.geomap/src/org/eclipse/nebula/widgets/geomap/internal/resources/world.png
Binary files differ