aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/org/traccar/web/client/Application.java16
-rw-r--r--src/org/traccar/web/client/controller/MapController.java26
-rw-r--r--src/org/traccar/web/client/view/ArchiveView.java21
-rw-r--r--src/org/traccar/web/client/view/MapPositionRenderer.java114
-rw-r--r--src/org/traccar/web/client/view/MapView.java125
-rw-r--r--src/org/traccar/web/client/view/MarkerIconFactory.java32
-rw-r--r--src/org/traccar/web/server/model/DataServiceImpl.java3
7 files changed, 258 insertions, 79 deletions
diff --git a/src/org/traccar/web/client/Application.java b/src/org/traccar/web/client/Application.java
index 22f20d8c..046dd734 100644
--- a/src/org/traccar/web/client/Application.java
+++ b/src/org/traccar/web/client/Application.java
@@ -5,6 +5,7 @@ import java.util.List;
import org.traccar.web.client.controller.ArchiveController;
import org.traccar.web.client.controller.DeviceController;
import org.traccar.web.client.controller.MapController;
+import org.traccar.web.client.model.BaseStoreHandlers;
import org.traccar.web.client.model.DataService;
import org.traccar.web.client.model.DataServiceAsync;
import org.traccar.web.client.view.ApplicationView;
@@ -13,6 +14,7 @@ import org.traccar.web.shared.model.Position;
import com.google.gwt.core.client.GWT;
import com.google.gwt.user.client.ui.RootPanel;
+import com.sencha.gxt.data.shared.event.StoreHandlers;
public class Application {
@@ -32,6 +34,7 @@ public class Application {
deviceController = new DeviceController(deviceHandler);
mapController = new MapController();
archiveController = new ArchiveController(archiveHanlder, deviceController.getDeviceStore());
+ archiveController.getPositionStore().addStoreHandlers(archiveStoreHandler);
view = new ApplicationView(
deviceController.getView(), mapController.getView(), archiveController.getView());
@@ -53,7 +56,7 @@ public class Application {
@Override
public void onSelected(Device device) {
- mapController.select(device);
+ mapController.selectDevice(device);
}
@Override
@@ -76,7 +79,16 @@ public class Application {
@Override
public void onSelected(Position position) {
- // TODO select something on map?
+ mapController.selectArchivePosition(position);
+ }
+
+ };
+
+ private StoreHandlers<Position> archiveStoreHandler = new BaseStoreHandlers<Position>() {
+
+ @Override
+ public void onAnything() {
+ mapController.showArchivePositions(archiveController.getPositionStore().getAll());
}
};
diff --git a/src/org/traccar/web/client/controller/MapController.java b/src/org/traccar/web/client/controller/MapController.java
index 5ab5bbcf..738b2811 100644
--- a/src/org/traccar/web/client/controller/MapController.java
+++ b/src/org/traccar/web/client/controller/MapController.java
@@ -1,5 +1,8 @@
package org.traccar.web.client.controller;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.LinkedList;
import java.util.List;
import org.traccar.web.client.Application;
@@ -13,7 +16,7 @@ import com.sencha.gxt.widget.core.client.ContentPanel;
public class MapController implements ContentController {
- private static final int UPDATE_INTERVAL = 10000;
+ private static final int UPDATE_INTERVAL = 15000;
private MapView mapView;
@@ -44,7 +47,7 @@ public class MapController implements ContentController {
Application.getDataService().getLatestPositions(new AsyncCallback<List<Position>>() {
@Override
public void onSuccess(List<Position> result) {
- mapView.showPositions(result);
+ mapView.showLatestPositions(result);
updateTimer.schedule(UPDATE_INTERVAL);
}
@Override
@@ -54,8 +57,23 @@ public class MapController implements ContentController {
});
}
- public void select(Device device) {
- mapView.select(device, true);
+ public void selectDevice(Device device) {
+ mapView.selectDevice(device);
+ }
+
+ public void showArchivePositions(List<Position> positions) {
+ List<Position> sortedPositions = new LinkedList<Position>(positions);
+ Collections.sort(sortedPositions, new Comparator<Position>() {
+ @Override
+ public int compare(Position o1, Position o2) {
+ return o1.getTime().compareTo(o2.getTime());
+ }
+ });
+ mapView.showArchivePositions(sortedPositions);
+ }
+
+ public void selectArchivePosition(Position position) {
+ mapView.selectArchivePosition(position);
}
}
diff --git a/src/org/traccar/web/client/view/ArchiveView.java b/src/org/traccar/web/client/view/ArchiveView.java
index f61ffccc..5d74f37c 100644
--- a/src/org/traccar/web/client/view/ArchiveView.java
+++ b/src/org/traccar/web/client/view/ArchiveView.java
@@ -28,8 +28,9 @@ import com.sencha.gxt.widget.core.client.form.TimeField;
import com.sencha.gxt.widget.core.client.grid.ColumnConfig;
import com.sencha.gxt.widget.core.client.grid.ColumnModel;
import com.sencha.gxt.widget.core.client.grid.Grid;
+import com.sencha.gxt.widget.core.client.selection.SelectionChangedEvent;
-public class ArchiveView {
+public class ArchiveView implements SelectionChangedEvent.SelectionChangedHandler<Position> {
private static ArchiveViewUiBinder uiBinder = GWT.create(ArchiveViewUiBinder.class);
@@ -107,6 +108,7 @@ public class ArchiveView {
uiBinder.createAndBindUi(this);
+ grid.getSelectionModel().addSelectionChangedHandler(this);
grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE);
// Initialize with current time
@@ -117,6 +119,15 @@ public class ArchiveView {
toTime.setValue(now);
}
+ @Override
+ public void onSelectionChanged(SelectionChangedEvent<Position> event) {
+ if (event.getSelection().isEmpty()) {
+ archiveHandler.onSelected(null);
+ } else {
+ archiveHandler.onSelected(event.getSelection().get(0));
+ }
+ }
+
@SuppressWarnings("deprecation")
private static Date getCombineDate(DateField dateField, TimeField timeField) {
Date result = null;
@@ -147,7 +158,13 @@ public class ArchiveView {
@Override
public void onAnything() {
- deviceCombo.setValue(deviceStore.findModel(deviceCombo.getValue()));
+ Device oldDevice = deviceCombo.getValue();
+ if (oldDevice != null) {
+ Device newDevice = deviceStore.findModel(oldDevice);
+ if (newDevice != null) {
+ deviceCombo.setValue(newDevice);
+ }
+ }
}
};
diff --git a/src/org/traccar/web/client/view/MapPositionRenderer.java b/src/org/traccar/web/client/view/MapPositionRenderer.java
new file mode 100644
index 00000000..5a756c78
--- /dev/null
+++ b/src/org/traccar/web/client/view/MapPositionRenderer.java
@@ -0,0 +1,114 @@
+package org.traccar.web.client.view;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.gwtopenmaps.openlayers.client.Icon;
+import org.gwtopenmaps.openlayers.client.Marker;
+import org.gwtopenmaps.openlayers.client.feature.VectorFeature;
+import org.gwtopenmaps.openlayers.client.geometry.LineString;
+import org.gwtopenmaps.openlayers.client.geometry.Point;
+import org.gwtopenmaps.openlayers.client.layer.Markers;
+import org.gwtopenmaps.openlayers.client.layer.Vector;
+import org.traccar.web.shared.model.Device;
+import org.traccar.web.shared.model.Position;
+
+
+public class MapPositionRenderer {
+
+ private final MapView mapView;
+ private final Vector vectorLayer;
+ private final Markers markerLayer;
+ private final MarkerIconFactory.IconType iconType;
+
+ public MapPositionRenderer(MapView mapView, MarkerIconFactory.IconType iconType) {
+ this.mapView = mapView;
+ vectorLayer = mapView.getVectorLayer();
+ markerLayer = mapView.getMarkerLayer();
+ this.iconType = iconType;
+ }
+
+ /*
+ * TODO: a lot of mess here
+ * 1. changeMarkerIcon doesn't save new marker
+ * 2. if device selected save device instead of position
+ * 3. find way to change marker icon
+ * 4. shorter cleaner methods
+ * ... maybe something else
+ */
+
+ private void changeMarkerIcon(Marker marker, Icon icon) {
+ Marker newMarker = new Marker(marker.getLonLat(), icon);
+ markerLayer.removeMarker(marker);
+ markerLayer.addMarker(newMarker);
+ }
+
+ private Map<Long, Marker> markerMap = new HashMap<Long, Marker>(); // Position.id -> Marker
+ private Map<Long, Long> deviceMap = new HashMap<Long, Long>(); // Device.id -> Position.id
+
+ private Long selectedPositionId;
+
+ public void showPositions(List<Position> positions) {
+ for (Marker marker : markerMap.values()) {
+ markerLayer.removeMarker(marker);
+ }
+ markerMap.clear();
+ deviceMap.clear();
+
+ for (Position position : positions) {
+ Marker marker = new Marker(
+ mapView.createLonLat(position.getLongitude(), position.getLatitude()),
+ MarkerIconFactory.getIcon(iconType, false));
+ markerMap.put(position.getId(), marker);
+ deviceMap.put(position.getDevice().getId(), position.getId());
+ markerLayer.addMarker(marker);
+ }
+
+ if (selectedPositionId != null) {
+ selectPosition(null, selectedPositionId, false);
+ }
+ }
+
+ public void showTrack(List<Position> positions) {
+ vectorLayer.destroyFeatures();
+
+ if (!positions.isEmpty()) {
+ Point[] linePoints = new Point[positions.size()];
+
+ int i = 0;
+ for (Position position : positions) {
+ linePoints[i++] = mapView.createPoint(position.getLongitude(), position.getLatitude());
+ }
+
+ LineString lineString = new LineString(linePoints);
+ vectorLayer.addFeature(new VectorFeature(lineString));
+ //mapView.getMap().zoomToExtent(lineString.getBounds());
+ }
+ }
+
+ public void selectPosition(Position position, boolean center) {
+ selectPosition(selectedPositionId, position.getId(), center);
+ }
+
+ public void selectDevice(Device device, boolean center) {
+ Long positionId = (device != null) ? deviceMap.get(device.getId()) : null;
+ selectPosition(selectedPositionId, positionId, center);
+ }
+
+ private void selectPosition(Long oldPositionId, Long newPositionId, boolean center) {
+ if (oldPositionId != null && markerMap.containsKey(oldPositionId)) {
+ changeMarkerIcon(markerMap.get(oldPositionId), MarkerIconFactory.getIcon(iconType, false));
+ selectedPositionId = null;
+ }
+ if (newPositionId != null && markerMap.containsKey(newPositionId)) {
+ Marker marker = markerMap.get(newPositionId);
+ changeMarkerIcon(marker, MarkerIconFactory.getIcon(iconType, true));
+ if (center) {
+ mapView.getMap().panTo(marker.getLonLat());
+ }
+ selectedPositionId = newPositionId;
+ }
+ }
+
+}
diff --git a/src/org/traccar/web/client/view/MapView.java b/src/org/traccar/web/client/view/MapView.java
index af38c443..a7d1dad2 100644
--- a/src/org/traccar/web/client/view/MapView.java
+++ b/src/org/traccar/web/client/view/MapView.java
@@ -1,21 +1,19 @@
package org.traccar.web.client.view;
-import java.util.AbstractMap;
-import java.util.HashMap;
import java.util.List;
-import org.gwtopenmaps.openlayers.client.Icon;
import org.gwtopenmaps.openlayers.client.LonLat;
import org.gwtopenmaps.openlayers.client.Map;
import org.gwtopenmaps.openlayers.client.MapOptions;
import org.gwtopenmaps.openlayers.client.MapWidget;
-import org.gwtopenmaps.openlayers.client.Marker;
-import org.gwtopenmaps.openlayers.client.Pixel;
import org.gwtopenmaps.openlayers.client.Projection;
-import org.gwtopenmaps.openlayers.client.Size;
import org.gwtopenmaps.openlayers.client.control.ScaleLine;
+import org.gwtopenmaps.openlayers.client.geometry.Point;
import org.gwtopenmaps.openlayers.client.layer.Markers;
+import org.gwtopenmaps.openlayers.client.layer.MarkersOptions;
import org.gwtopenmaps.openlayers.client.layer.OSM;
+import org.gwtopenmaps.openlayers.client.layer.Vector;
+import org.gwtopenmaps.openlayers.client.layer.VectorOptions;
import org.traccar.web.shared.model.Device;
import org.traccar.web.shared.model.Position;
@@ -25,34 +23,7 @@ import com.google.gwt.event.logical.shared.ResizeHandler;
import com.google.gwt.user.client.Command;
import com.sencha.gxt.widget.core.client.ContentPanel;
-class MarkerIconFactory {
- private static final Size iconSize = new Size(21, 25);
- private static final Pixel iconOffset = new Pixel(-10.5f, -25.0f);
-
- private static final String iconUrl = "http://www.openlayers.org/api/img/";
- private static final String iconRed = iconUrl + "marker.png";
- private static final String iconBlue = iconUrl + "marker-blue.png";
- private static final String iconGreen = iconUrl + "marker-green.png";
- private static final String iconGold = iconUrl + "marker-gold.png";
-
- public static Icon getLocationIcon() {
- return new Icon(iconRed, iconSize, iconOffset);
- }
-
- public static Icon getSelectedLocationIcon() {
- return new Icon(iconGreen, iconSize, iconOffset);
- }
-
- public static Icon getArchiveIcon() {
- return new Icon(iconBlue, iconSize, iconOffset);
- }
-
- public static Icon getSelectedArchiveIcon() {
- return new Icon(iconGold, iconSize, iconOffset);
- }
-
-}
public class MapView {
@@ -64,11 +35,30 @@ public class MapView {
private MapWidget mapWidget;
private Map map;
+ private Vector vectorLayer;
private Markers markerLayer;
- private LonLat createPoint(double longitude, double latitude) {
- LonLat point = new LonLat(longitude, latitude);
- point.transform(new Projection("EPSG:4326").getProjectionCode(), map.getProjection());
+ public Map getMap() {
+ return map;
+ }
+
+ public Vector getVectorLayer() {
+ return vectorLayer;
+ }
+
+ public Markers getMarkerLayer() {
+ return markerLayer;
+ }
+
+ public LonLat createLonLat(double longitude, double latitude) {
+ LonLat lonLat = new LonLat(longitude, latitude);
+ lonLat.transform(new Projection("EPSG:4326").getProjectionCode(), map.getProjection());
+ return lonLat;
+ }
+
+ public Point createPoint(double x, double y) {
+ Point point = new Point(x, y);
+ point.transform(new Projection("EPSG:4326"), new Projection(map.getProjection()));
return point;
}
@@ -78,6 +68,8 @@ public class MapView {
MapOptions defaultMapOptions = new MapOptions();
defaultMapOptions.setNumZoomLevels(16);
+ defaultMapOptions.setProjection("EPSG:4326");
+ defaultMapOptions.setDisplayProjection(new Projection("EPSG:4326"));
mapWidget = new MapWidget("100%", "100%", defaultMapOptions);
map = mapWidget.getMap();
@@ -85,12 +77,19 @@ public class MapView {
OSM mapLayer = OSM.Mapnik("Mapnik");
mapLayer.setIsBaseLayer(true);
- markerLayer = new Markers("Markers");
+ VectorOptions vectorOptions = new VectorOptions();
+ vectorOptions.setProjection("EPSG:4326");
+ vectorLayer = new Vector("Vector", vectorOptions);
+
+ MarkersOptions markersOptions = new MarkersOptions();
+ markersOptions.setProjection("EPSG:4326");
+ markerLayer = new Markers("Markers", markersOptions);
map.addLayer(mapLayer);
+ map.addLayer(vectorLayer);
map.addLayer(markerLayer);
map.addControl(new ScaleLine());
- map.setCenter(createPoint(30, 60), 1);
+ map.setCenter(createLonLat(12.5, 41.9), 1);
contentPanel.add(mapWidget);
@@ -106,44 +105,30 @@ public class MapView {
});
}
});
+
+ latestPositionRenderer = new MapPositionRenderer(this, MarkerIconFactory.IconType.iconLatest);
+ archivePositionRenderer = new MapPositionRenderer(this, MarkerIconFactory.IconType.iconArchive);
+ }
+
+ private final MapPositionRenderer latestPositionRenderer;
+
+ private final MapPositionRenderer archivePositionRenderer;
+
+ public void showLatestPositions(List<Position> positions) {
+ latestPositionRenderer.showPositions(positions);
}
- private AbstractMap<Long, Marker> markerMap = new HashMap<Long, Marker>();
- private Device selectedDevice;
-
- public void showPositions(List<Position> positions) {
- markerMap.clear();
- markerLayer.clearMarkers();
- for (Position position : positions) {
- Marker marker = new Marker(
- createPoint(position.getLongitude(), position.getLatitude()), MarkerIconFactory.getLocationIcon());
- markerMap.put(position.getDevice().getId(), marker);
- markerLayer.addMarker(marker);
- }
- if (selectedDevice != null) {
- select(selectedDevice, false);
- }
+ public void showArchivePositions(List<Position> positions) {
+ archivePositionRenderer.showTrack(positions);
+ archivePositionRenderer.showPositions(positions);
}
- private void changeMarkerIcon(Marker marker, Icon icon) {
- Marker newMarker = new Marker(marker.getLonLat(), icon);
- markerLayer.removeMarker(marker);
- markerLayer.addMarker(newMarker);
+ public void selectDevice(Device device) {
+ latestPositionRenderer.selectDevice(device, true);
}
- public void select(Device device, boolean center) {
- if (selectedDevice != null) {
- changeMarkerIcon(markerMap.get(selectedDevice.getId()), MarkerIconFactory.getLocationIcon());
- selectedDevice = null;
- }
- if (device != null && markerMap.containsKey(device.getId())) {
- Marker marker = markerMap.get(device.getId());
- if (center) {
- map.panTo(marker.getLonLat());
- }
- changeMarkerIcon(marker, MarkerIconFactory.getSelectedLocationIcon());
- selectedDevice = device;
- }
+ public void selectArchivePosition(Position position) {
+ archivePositionRenderer.selectPosition(position, true);
}
}
diff --git a/src/org/traccar/web/client/view/MarkerIconFactory.java b/src/org/traccar/web/client/view/MarkerIconFactory.java
new file mode 100644
index 00000000..484a6a40
--- /dev/null
+++ b/src/org/traccar/web/client/view/MarkerIconFactory.java
@@ -0,0 +1,32 @@
+package org.traccar.web.client.view;
+
+import org.gwtopenmaps.openlayers.client.Icon;
+import org.gwtopenmaps.openlayers.client.Pixel;
+import org.gwtopenmaps.openlayers.client.Size;
+
+class MarkerIconFactory {
+
+ private static final Size iconSize = new Size(21, 25);
+ private static final Pixel iconOffset = new Pixel(-10.5f, -25.0f);
+
+ private static final String iconUrl = "http://www.openlayers.org/api/img/";
+ private static final String iconRed = iconUrl + "marker.png";
+ private static final String iconBlue = iconUrl + "marker-blue.png";
+ private static final String iconGreen = iconUrl + "marker-green.png";
+ private static final String iconGold = iconUrl + "marker-gold.png";
+
+ public static enum IconType {
+ iconLatest,
+ iconArchive
+ };
+
+ public static Icon getIcon(IconType type, boolean selected) {
+ if (type == IconType.iconLatest) {
+ return new Icon(selected ? iconGreen : iconRed, iconSize, iconOffset);
+ } else if (type == IconType.iconArchive) {
+ return new Icon(selected ? iconGold : iconBlue, iconSize, iconOffset);
+ }
+ return null;
+ }
+
+}
diff --git a/src/org/traccar/web/server/model/DataServiceImpl.java b/src/org/traccar/web/server/model/DataServiceImpl.java
index f9d0e7e3..9c69b48e 100644
--- a/src/org/traccar/web/server/model/DataServiceImpl.java
+++ b/src/org/traccar/web/server/model/DataServiceImpl.java
@@ -142,7 +142,8 @@ public class DataServiceImpl extends RemoteServiceServlet implements DataService
try {
device = entityManager.merge(device);
user.getDevices().remove(device);
- entityManager.remove(device);
+ // If you want to remove device you need to remove all linked positions
+ //entityManager.remove(device);
entityManager.getTransaction().commit();
} catch (Exception e) {
entityManager.getTransaction().rollback();