From f0b99fd68cb3b6b484d50c1f9ebc0e77997fd2dd Mon Sep 17 00:00:00 2001 From: Anton Tananaev Date: Wed, 9 Jan 2013 20:32:40 +1300 Subject: Completely rewritten project --- .../traccar/web/client/view/ApplicationView.java | 33 +++++ .../traccar/web/client/view/ApplicationView.ui.xml | 42 ++++++ src/org/traccar/web/client/view/ArchiveView.java | 79 +++++++++++ src/org/traccar/web/client/view/ArchiveView.ui.xml | 60 +++++++++ src/org/traccar/web/client/view/DeviceDialog.java | 69 ++++++++++ .../traccar/web/client/view/DeviceDialog.ui.xml | 40 ++++++ src/org/traccar/web/client/view/DeviceView.java | 128 ++++++++++++++++++ src/org/traccar/web/client/view/DeviceView.ui.xml | 46 +++++++ src/org/traccar/web/client/view/LoginDialog.java | 59 ++++++++ src/org/traccar/web/client/view/LoginDialog.ui.xml | 40 ++++++ src/org/traccar/web/client/view/MapView.java | 149 +++++++++++++++++++++ 11 files changed, 745 insertions(+) create mode 100644 src/org/traccar/web/client/view/ApplicationView.java create mode 100644 src/org/traccar/web/client/view/ApplicationView.ui.xml create mode 100644 src/org/traccar/web/client/view/ArchiveView.java create mode 100644 src/org/traccar/web/client/view/ArchiveView.ui.xml create mode 100644 src/org/traccar/web/client/view/DeviceDialog.java create mode 100644 src/org/traccar/web/client/view/DeviceDialog.ui.xml create mode 100644 src/org/traccar/web/client/view/DeviceView.java create mode 100644 src/org/traccar/web/client/view/DeviceView.ui.xml create mode 100644 src/org/traccar/web/client/view/LoginDialog.java create mode 100644 src/org/traccar/web/client/view/LoginDialog.ui.xml create mode 100644 src/org/traccar/web/client/view/MapView.java (limited to 'src/org/traccar/web/client/view') diff --git a/src/org/traccar/web/client/view/ApplicationView.java b/src/org/traccar/web/client/view/ApplicationView.java new file mode 100644 index 00000000..bff8854f --- /dev/null +++ b/src/org/traccar/web/client/view/ApplicationView.java @@ -0,0 +1,33 @@ +package org.traccar.web.client.view; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.sencha.gxt.widget.core.client.ContentPanel; + +public class ApplicationView extends Composite { + + private static ApplicationViewUiBinder uiBinder = GWT.create(ApplicationViewUiBinder.class); + + interface ApplicationViewUiBinder extends UiBinder { + } + + @UiField(provided = true) + ContentPanel devicePanel; + + @UiField(provided = true) + ContentPanel mapPanel; + + @UiField(provided = true) + ContentPanel archivePanel; + + public ApplicationView(ContentPanel deviceView, ContentPanel mapView, ContentPanel archiveView) { + devicePanel = deviceView; + mapPanel = mapView; + archivePanel = archiveView; + initWidget(uiBinder.createAndBindUi(this)); + } + +} diff --git a/src/org/traccar/web/client/view/ApplicationView.ui.xml b/src/org/traccar/web/client/view/ApplicationView.ui.xml new file mode 100644 index 00000000..2faae1e7 --- /dev/null +++ b/src/org/traccar/web/client/view/ApplicationView.ui.xml @@ -0,0 +1,42 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/org/traccar/web/client/view/ArchiveView.java b/src/org/traccar/web/client/view/ArchiveView.java new file mode 100644 index 00000000..79621ba9 --- /dev/null +++ b/src/org/traccar/web/client/view/ArchiveView.java @@ -0,0 +1,79 @@ +package org.traccar.web.client.view; + +import java.util.Date; +import java.util.LinkedList; +import java.util.List; + +import org.traccar.web.client.model.PositionProperties; +import org.traccar.web.shared.model.Position; + +import com.google.gwt.cell.client.DateCell; +import com.google.gwt.core.client.GWT; +import com.google.gwt.i18n.client.DateTimeFormat; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.sencha.gxt.data.shared.ListStore; +import com.sencha.gxt.widget.core.client.ContentPanel; +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; + +public class ArchiveView extends Composite { + + private static ArchiveViewUiBinder uiBinder = GWT.create(ArchiveViewUiBinder.class); + + interface ArchiveViewUiBinder extends UiBinder { + } + + public interface ArchiveHandler { + public void onSelected(Position position); + } + + private ArchiveHandler archiveHandler; + + @UiField + ContentPanel contentPanel; + + public ContentPanel getView() { + return contentPanel; + } + + @UiField(provided = true) + ColumnModel columnModel; + + @UiField(provided = true) + ListStore store; + + @UiField + Grid grid; + + public ArchiveView(ArchiveHandler archiveHandler) { + this.archiveHandler = archiveHandler; + + PositionProperties positionProperties = GWT.create(PositionProperties.class); + + List> columnConfigList = new LinkedList>(); + + columnConfigList.add(new ColumnConfig(positionProperties.valid(), 0, "Valid")); + + ColumnConfig columnConfig = new ColumnConfig(positionProperties.time(), 0, "Time"); + columnConfig.setCell(new DateCell(DateTimeFormat.getFormat("yyyy-MM-dd HH:mm:ss"))); + columnConfigList.add(columnConfig); + + columnConfigList.add(new ColumnConfig(positionProperties.latitude(), 0, "Latitude")); + columnConfigList.add(new ColumnConfig(positionProperties.longitude(), 0, "Longitude")); + columnConfigList.add(new ColumnConfig(positionProperties.altitude(), 0, "Altitude")); + columnConfigList.add(new ColumnConfig(positionProperties.speed(), 0, "Speed")); + columnConfigList.add(new ColumnConfig(positionProperties.course(), 0, "Course")); + columnConfigList.add(new ColumnConfig(positionProperties.power(), 0, "Power")); + + columnModel = new ColumnModel(columnConfigList); + + store = new ListStore(positionProperties.id()); + + uiBinder.createAndBindUi(this); + } + +} diff --git a/src/org/traccar/web/client/view/ArchiveView.ui.xml b/src/org/traccar/web/client/view/ArchiveView.ui.xml new file mode 100644 index 00000000..370eb024 --- /dev/null +++ b/src/org/traccar/web/client/view/ArchiveView.ui.xml @@ -0,0 +1,60 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/org/traccar/web/client/view/DeviceDialog.java b/src/org/traccar/web/client/view/DeviceDialog.java new file mode 100644 index 00000000..891dd4ef --- /dev/null +++ b/src/org/traccar/web/client/view/DeviceDialog.java @@ -0,0 +1,69 @@ +package org.traccar.web.client.view; + +import org.traccar.web.shared.model.Device; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.editor.client.Editor; +import com.google.gwt.editor.client.SimpleBeanEditorDriver; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.ui.Widget; +import com.sencha.gxt.widget.core.client.Window; +import com.sencha.gxt.widget.core.client.event.SelectEvent; +import com.sencha.gxt.widget.core.client.form.TextField; + +public class DeviceDialog implements Editor { + + private static DeviceDialogUiBinder uiBinder = GWT.create(DeviceDialogUiBinder.class); + + interface DeviceDialogUiBinder extends UiBinder { + } + + private DeviceDriver driver = GWT.create(DeviceDriver.class); + + interface DeviceDriver extends SimpleBeanEditorDriver { + } + + public interface DeviceHandler { + public void onSave(Device device); + } + + private DeviceHandler deviceHandler; + + @UiField + Window window; + + @UiField + TextField name; + + @UiField + TextField uniqueId; + + public DeviceDialog(Device device, DeviceHandler deviceHandler) { + this.deviceHandler = deviceHandler; + uiBinder.createAndBindUi(this); + driver.initialize(this); + driver.edit(device); + } + + public void show() { + window.show(); + } + + public void hide() { + window.hide(); + } + + @UiHandler("saveButton") + public void onLoginClicked(SelectEvent event) { + window.hide(); + deviceHandler.onSave(driver.flush()); + } + + @UiHandler("cancelButton") + public void onRegisterClicked(SelectEvent event) { + window.hide(); + } + +} diff --git a/src/org/traccar/web/client/view/DeviceDialog.ui.xml b/src/org/traccar/web/client/view/DeviceDialog.ui.xml new file mode 100644 index 00000000..4f7ccc56 --- /dev/null +++ b/src/org/traccar/web/client/view/DeviceDialog.ui.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/org/traccar/web/client/view/DeviceView.java b/src/org/traccar/web/client/view/DeviceView.java new file mode 100644 index 00000000..157973e0 --- /dev/null +++ b/src/org/traccar/web/client/view/DeviceView.java @@ -0,0 +1,128 @@ +package org.traccar.web.client.view; + +import java.util.Collection; +import java.util.LinkedList; +import java.util.List; + +import org.traccar.web.client.model.DeviceProperties; +import org.traccar.web.shared.model.Device; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.ui.Composite; +import com.google.gwt.user.client.ui.Widget; +import com.sencha.gxt.core.client.Style.SelectionMode; +import com.sencha.gxt.data.shared.ListStore; +import com.sencha.gxt.widget.core.client.ContentPanel; +import com.sencha.gxt.widget.core.client.button.TextButton; +import com.sencha.gxt.widget.core.client.event.SelectEvent; +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 DeviceView extends Composite implements SelectionChangedEvent.SelectionChangedHandler { + + private static DeviceViewUiBinder uiBinder = GWT.create(DeviceViewUiBinder.class); + + interface DeviceViewUiBinder extends UiBinder { + } + + public interface DeviceHandler { + public void onSelected(Device device); + public void onAdd(); + public void onEdit(Device device); + public void onRemove(Device device); + } + + private DeviceHandler deviceHandler; + + @UiField + ContentPanel contentPanel; + + public ContentPanel getView() { + return contentPanel; + } + + @UiField + TextButton addButton; + + @UiField + TextButton editButton; + + @UiField + TextButton removeButton; + + @UiField(provided = true) + ColumnModel columnModel; + + @UiField(provided = true) + ListStore store; + + @UiField + Grid grid; + + public DeviceView(DeviceHandler deviceHandler) { + this.deviceHandler = deviceHandler; + + DeviceProperties deviceProperties = GWT.create(DeviceProperties.class); + + List> columnConfigList = new LinkedList>(); + columnConfigList.add(new ColumnConfig(deviceProperties.name(), 0, "Name")); + columnConfigList.add(new ColumnConfig(deviceProperties.uniqueId(), 0, "Unique Identifier")); + columnModel = new ColumnModel(columnConfigList); + + store = new ListStore(deviceProperties.id()); + + uiBinder.createAndBindUi(this); + + grid.getSelectionModel().addSelectionChangedHandler(this); + grid.getSelectionModel().setSelectionMode(SelectionMode.SINGLE); + } + + @Override + public void onSelectionChanged(SelectionChangedEvent event) { + editButton.setEnabled(!event.getSelection().isEmpty()); + removeButton.setEnabled(!event.getSelection().isEmpty()); + + if (event.getSelection().isEmpty()) { + deviceHandler.onSelected(null); + } else { + deviceHandler.onSelected(event.getSelection().get(0)); + } + } + + public void load(Collection devices) { + store.addAll(devices); + } + + @UiHandler("addButton") + public void onAddClicked(SelectEvent event) { + deviceHandler.onAdd(); + } + + public void add(Device device) { + store.add(store.size(), device); + } + + @UiHandler("editButton") + public void onEditClicked(SelectEvent event) { + deviceHandler.onEdit(grid.getSelectionModel().getSelectedItem()); + } + + public void update(Device device) { + store.update(device); + } + + @UiHandler("removeButton") + public void onRemoveClicked(SelectEvent event) { + deviceHandler.onRemove(grid.getSelectionModel().getSelectedItem()); + } + + public void remove(Device device) { + store.remove(device); + } + +} diff --git a/src/org/traccar/web/client/view/DeviceView.ui.xml b/src/org/traccar/web/client/view/DeviceView.ui.xml new file mode 100644 index 00000000..d9988d5e --- /dev/null +++ b/src/org/traccar/web/client/view/DeviceView.ui.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/org/traccar/web/client/view/LoginDialog.java b/src/org/traccar/web/client/view/LoginDialog.java new file mode 100644 index 00000000..44474179 --- /dev/null +++ b/src/org/traccar/web/client/view/LoginDialog.java @@ -0,0 +1,59 @@ +package org.traccar.web.client.view; + +import com.google.gwt.core.client.GWT; +import com.google.gwt.uibinder.client.UiBinder; +import com.google.gwt.uibinder.client.UiField; +import com.google.gwt.uibinder.client.UiHandler; +import com.google.gwt.user.client.ui.Widget; +import com.sencha.gxt.widget.core.client.Window; +import com.sencha.gxt.widget.core.client.event.SelectEvent; +import com.sencha.gxt.widget.core.client.form.PasswordField; +import com.sencha.gxt.widget.core.client.form.TextField; + +public class LoginDialog { + + private static LoginDialogUiBinder uiBinder = GWT.create(LoginDialogUiBinder.class); + + interface LoginDialogUiBinder extends UiBinder { + } + + public interface LoginHandler { + public void onLogin(String login, String password); + public void onRegister(String login, String password); + } + + private LoginHandler loginHandler; + + @UiField + Window window; + + @UiField + TextField login; + + @UiField + PasswordField password; + + public LoginDialog(LoginHandler loginHandler) { + this.loginHandler = loginHandler; + uiBinder.createAndBindUi(this); + } + + public void show() { + window.show(); + } + + public void hide() { + window.hide(); + } + + @UiHandler("loginButton") + public void onLoginClicked(SelectEvent event) { + loginHandler.onLogin(login.getText(), password.getText()); + } + + @UiHandler("registerButton") + public void onRegisterClicked(SelectEvent event) { + loginHandler.onRegister(login.getText(), password.getText()); + } + +} diff --git a/src/org/traccar/web/client/view/LoginDialog.ui.xml b/src/org/traccar/web/client/view/LoginDialog.ui.xml new file mode 100644 index 00000000..8c31b308 --- /dev/null +++ b/src/org/traccar/web/client/view/LoginDialog.ui.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/org/traccar/web/client/view/MapView.java b/src/org/traccar/web/client/view/MapView.java new file mode 100644 index 00000000..af38c443 --- /dev/null +++ b/src/org/traccar/web/client/view/MapView.java @@ -0,0 +1,149 @@ +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.layer.Markers; +import org.gwtopenmaps.openlayers.client.layer.OSM; +import org.traccar.web.shared.model.Device; +import org.traccar.web.shared.model.Position; + +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.event.logical.shared.ResizeEvent; +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 { + + private ContentPanel contentPanel; + + public ContentPanel getView() { + return contentPanel; + } + + private MapWidget mapWidget; + private Map map; + 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()); + return point; + } + + public MapView() { + contentPanel = new ContentPanel(); + contentPanel.setHeadingText("Map"); + + MapOptions defaultMapOptions = new MapOptions(); + defaultMapOptions.setNumZoomLevels(16); + + mapWidget = new MapWidget("100%", "100%", defaultMapOptions); + map = mapWidget.getMap(); + + OSM mapLayer = OSM.Mapnik("Mapnik"); + mapLayer.setIsBaseLayer(true); + + markerLayer = new Markers("Markers"); + + map.addLayer(mapLayer); + map.addLayer(markerLayer); + map.addControl(new ScaleLine()); + map.setCenter(createPoint(30, 60), 1); + + contentPanel.add(mapWidget); + + // Update map size + contentPanel.addResizeHandler(new ResizeHandler() { + @Override + public void onResize(ResizeEvent event) { + Scheduler.get().scheduleDeferred(new Command() { + @Override + public void execute() { + map.updateSize(); + } + }); + } + }); + } + + private AbstractMap markerMap = new HashMap(); + private Device selectedDevice; + + public void showPositions(List 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); + } + } + + private void changeMarkerIcon(Marker marker, Icon icon) { + Marker newMarker = new Marker(marker.getLonLat(), icon); + markerLayer.removeMarker(marker); + markerLayer.addMarker(newMarker); + } + + 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; + } + } + +} -- cgit v1.2.3