Implementing virtual synchronizing mechanism
MODIFY
plugin.xml
plugin.xml
<js-module name="StreetViewPanorama" src="www/StreetViewPanorama.js">
<runs />
</js-module>
+ <js-module name="Overlay" src="www/Overlay.js">
+ <runs />
+ </js-module>
<description>Google Maps native SDK for Android and iOS.
This plugin allows your application to use the native Google Maps views instead of the Google Maps JavaScript API v3.

MODIFY
src/android/plugin/google/maps/PluginMarker.java
src/android/plugin/google/maps/PluginMarker.java
@@ -197,7 +197,7 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
// Create an instance of Marker class
JSONObject opts = args.getJSONObject(1);
- final String markerId = "marker_" + callbackContext.hashCode();
+ final String markerId = args.getString(2);
final JSONObject result = new JSONObject();
result.put("id", markerId);
@@ -593,6 +593,11 @@ public class PluginMarker extends MyPlugin implements MyPluginInterface {
String markerId = args.getString(0);
String animation = args.getString(1);
final Marker marker = this.getMarker(markerId);
+ Log.d(TAG, "--->setAnimation: markerId = " + markerId + ", animation = " + animation);
+ if (marker == null) {
+ callbackContext.error("marker is null");
+ return;
+ }
this.setMarkerAnimation_(marker, animation, new PluginAsyncInterface() {

MODIFY
www/CordovaGoogleMaps.js
www/CordovaGoogleMaps.js
@@ -694,6 +694,10 @@ CordovaGoogleMaps.prototype.getPanorama = function(div, streetViewOptions) {
// Create a panorama instance.
var panorama = new StreetViewPanorama(mapId, self.execCmd);
+ // Catch all events for this map instance, then pass to the instance.
+ // (Don't execute this native callback from your code)
+ plugin.google.maps[mapId] = nativeCallback.bind(panorama);
+
self.MAP_CNT++;
self.MAPS[mapId] = panorama;
self.isThereAnyChange = true;

MODIFY
www/Map.js
www/Map.js
@@ -1151,7 +1151,10 @@ Map.prototype.addCircle = function(circleOptions, callback) {
Map.prototype.addMarker = function(markerOptions, callback) {
var self = this;
markerOptions = common.markerOptionsFilter(markerOptions);
- exec.call(this, function(result) {
+
+ //------------------------------------
+ // Generate a makrer instance at once.
+ //------------------------------------
markerOptions.icon = markerOptions.icon || {};
if (typeof markerOptions.icon === 'string' || Array.isArray(markerOptions.icon)) {
markerOptions.icon = {
@@ -1159,6 +1162,20 @@ Map.prototype.addMarker = function(markerOptions, callback) {
size: {}
};
}
+
+ var markerId = "marker_" + (Math.floor(Date.now() * Math.random()));
+ var marker = new Marker(self, markerId, markerOptions, "Marker", exec);
+ self.MARKERS[markerId] = marker;
+ self.OVERLAYS[markerId] = marker;
+ marker.one(markerId + "_remove", function() {
+ delete self.MARKERS[markerId];
+ delete self.OVERLAYS[markerId];
+ marker.destroy();
+ marker = undefined;
+ });
+
+ exec.call(this, function(result) {
+
markerOptions.icon.size = markerOptions.icon.size || {};
markerOptions.icon.size.width = markerOptions.icon.size.width || result.width;
markerOptions.icon.size.height = markerOptions.icon.size.height || result.height;
@@ -1167,23 +1184,15 @@ Map.prototype.addMarker = function(markerOptions, callback) {
if (!markerOptions.infoWindowAnchor) {
markerOptions.infoWindowAnchor = [markerOptions.icon.size.width / 2, 0];
}
-
- var marker = new Marker(self, result.id, markerOptions, "Marker", exec);
-
- self.MARKERS[result.id] = marker;
- self.OVERLAYS[result.id] = marker;
-
- marker.one(result.id + "_remove", function() {
- marker.off();
- delete self.MARKERS[result.id];
- delete self.OVERLAYS[result.id];
- marker = undefined;
- });
+ marker._privateInitialize(markerOptions);
+ delete marker._privateInitialize;
if (typeof callback === "function") {
callback.call(self, marker);
}
- }, self.errorHandler, self.id, 'loadPlugin', ['Marker', markerOptions]);
+ }, self.errorHandler, self.id, 'loadPlugin', ['Marker', markerOptions, markerId]);
+
+ return marker;
};

MODIFY
www/Marker.js
www/Marker.js
@@ -3,43 +3,16 @@ var argscheck = require('cordova/argscheck'),
common = require('./Common'),
LatLng = require('./LatLng'),
event = require('./event'),
- BaseClass = require('./BaseClass');
+ Overlay = require('./Overlay');
/*****************************************************************************
* Marker Class
*****************************************************************************/
-var exec;
var Marker = function(map, id, markerOptions, className, _exec) {
- exec = _exec;
- BaseClass.apply(this);
+ Overlay.call(this, map, id, className, _exec);
var self = this;
- Object.defineProperty(self, "_isReady", {
- value: true,
- writable: false
- });
- Object.defineProperty(self, "map", {
- value: map,
- writable: false
- });
- Object.defineProperty(self, "id", {
- value: id,
- writable: false
- });
- Object.defineProperty(self, "type", {
- value: className,
- writable: false
- });
-
- className = className.toLowerCase();
- Object.defineProperty(self, "getPluginName", {
- writable: false,
- value: function() {
- return this.map.getId() + "-" + className.toLowerCase();
- }
- });
-
if (markerOptions && markerOptions.position) {
self.set('position', markerOptions.position);
}
@@ -63,66 +36,93 @@ var Marker = function(map, id, markerOptions, className, _exec) {
self.on("position_changed", function() {
var position = self.get("position");
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setPosition', [self.getId(), position.lat, position.lng]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setPosition', [self.getId(), position.lat, position.lng]);
});
self.on("rotation_changed", function() {
var rotation = self.get("rotation");
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setRotation', [self.getId(), rotation]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setRotation', [self.getId(), rotation]);
});
self.on("snippet_changed", function() {
var snippet = self.get("snippet");
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setSnippet', [self.getId(), snippet]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setSnippet', [self.getId(), snippet]);
});
self.on("visible_changed", function() {
var visible = self.get("visible");
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setVisible', [self.getId(), visible]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setVisible', [self.getId(), visible]);
});
self.on("title_changed", function() {
var title = self.get("title");
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setTitle', [self.getId(), title]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setTitle', [self.getId(), title]);
});
self.on("icon_changed", function() {
var icon = self.get("icon");
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setIcon', [self.getId(), icon]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setIcon', [self.getId(), icon]);
});
self.on("flat_changed", function() {
var flat = self.get("flat");
flat = flat === true;
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setFlat', [self.getId(), flat]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setFlat', [self.getId(), flat]);
});
self.on("draggable_changed", function() {
var draggable = self.get("draggable");
draggable = draggable === true;
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setDraggable', [self.getId(), draggable]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setDraggable', [self.getId(), draggable]);
});
self.on("anchor_changed", function() {
var anchor = self.get("anchor");
- if (!anchor) { return; }
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setIconAnchor', [self.getId(), anchor[0], anchor[1]]);
+ if (!anchor) {
+ return;
+ }
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setIconAnchor', [self.getId(), anchor[0], anchor[1]]);
});
self.on("infoWindowAnchor_changed", function() {
var anchor = self.get("infoWindowAnchor");
- if (!anchor) { return; }
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setInfoWindowAnchor', [self.getId(), anchor[0], anchor[1]]);
+ if (!anchor) {
+ return;
+ }
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setInfoWindowAnchor', [self.getId(), anchor[0], anchor[1]]);
});
self.on("zIndex_changed", function() {
var zIndex = self.get("zIndex");
- if (zIndex === null || zIndex === undefined) { return; }
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setZIndex', [self.getId(), zIndex]);
+ if (zIndex === null || zIndex === undefined) {
+ return;
+ }
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setZIndex', [self.getId(), zIndex]);
});
self.on("opacity_changed", function() {
var opacity = self.get("opacity");
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setOpacity', [self.getId(), opacity]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setOpacity', [self.getId(), opacity]);
});
self.on("disableAutoPan_changed", function() {
var disableAutoPan = self.get("disableAutoPan");
- exec.call(self, null, self.errorHandler, self.getPluginName(), 'setDisableAutoPan', [self.getId(), disableAutoPan]);
+ self.exec.call(self, null, self.errorHandler, self.getPluginName(), 'setDisableAutoPan', [self.getId(), disableAutoPan]);
});
};
-utils.extend(Marker, BaseClass);
+utils.extend(Marker, Overlay);
+Marker.prototype._privateInitialize = function(markerOptions) {
+ var self = this;
+ //-----------------------------------------------
+ // Sets the initialize option to each property
+ //-----------------------------------------------
+ var ignores = ["map", "id", "hashCode", "type"];
+ for (var key in markerOptions) {
+ if (ignores.indexOf(key) === -1) {
+ self.set(key, markerOptions[key], true);
+ }
+ }
+
+ //-----------------------------------------------
+ // Trigger internal command queue
+ //-----------------------------------------------
+ Object.defineProperty(self, "_isReady", {
+ value: true,
+ writable: false
+ });
+ self.exec("nop");
+};
Marker.prototype.remove = function(callback) {
var self = this;
if (self._isRemoved) {
@@ -134,12 +134,14 @@ Marker.prototype.remove = function(callback) {
});
self.trigger(event.INFO_CLOSE); // close open infowindow, otherwise it will stay
self.trigger(self.id + "_remove");
- exec.call(self, function() {
+ self.exec.call(self, function() {
self.destroy();
if (typeof callback === "function") {
callback.call(self);
}
- }, self.errorHandler, self.getPluginName(), 'remove', [self.getId()], {remove: true});
+ }, self.errorHandler, self.getPluginName(), 'remove', [self.getId()], {
+ remove: true
+ });
};
@@ -186,8 +188,7 @@ Marker.prototype.setAnimation = function(animation, callback) {
return;
}
this.set("animation", animation);
-
- exec.call(self, function() {
+ self.exec.call(self, function() {
if (typeof callback === "function") {
callback.call(self);
}
@@ -292,7 +293,9 @@ Marker.prototype.showInfoWindow = function() {
}
this.set("isInfoWindowVisible", true);
this.map.set("active_marker_id", this.id);
- exec.call(this, null, this.errorHandler, this.getPluginName(), 'showInfoWindow', [this.getId()], {sync: true});
+ self.exec.call(this, null, this.errorHandler, this.getPluginName(), 'showInfoWindow', [this.getId()], {
+ sync: true
+ });
return this;
};
Marker.prototype.hideInfoWindow = function() {
@@ -301,7 +304,9 @@ Marker.prototype.hideInfoWindow = function() {
}
if (this.get("isInfoWindowVisible")) {
this.set("isInfoWindowVisible", false);
- exec.call(this, null, this.errorHandler, this.getPluginName(), 'hideInfoWindow', [this.getId()], {sync: true});
+ self.exec.call(this, null, this.errorHandler, this.getPluginName(), 'hideInfoWindow', [this.getId()], {
+ sync: true
+ });
}
return this;
};

ADD
www/Overlay.js
+var BaseClass = require('./BaseClass'),
+ utils = require('cordova/utils'),
+ BaseArrayClass = require('./BaseArrayClass');
+
+
+/*****************************************************************************
+ * Overlay Class
+ *****************************************************************************/
+var Overlay = function(map, id, className, _exec) {
+ BaseClass.apply(this);
+
+ var self = this;
+
+ //-------------------------------------------------------------------------------
+ // If app code wants to execute some method before `_isReady = true`,
+ // just stack in to the internal queue.
+ // If this overlay is ready, execute it.
+ //-------------------------------------------------------------------------------
+ var cmdQueue = new BaseArrayClass();
+ cmdQueue.on('insert_at', function() {
+ if (!self._isReady) {
+ return;
+ }
+ var cmd;
+ while(cmdQueue.getLength() > 0) {
+ cmd = cmdQueue.removeAt(0, true);
+ if (cmd && cmd.target && cmd.args && cmd.args[0] !== "nop") {
+ _exec.apply(cmd.target, cmd.args);
+ }
+ }
+ });
+
+
+ Object.defineProperty(self, "_cmdQueue", {
+ enumerable: false,
+ value: cmdQueue,
+ writable: false
+ });
+
+ Object.defineProperty(self, "_isReady", {
+ value: false,
+ writable: true
+ });
+ Object.defineProperty(self, "map", {
+ value: map,
+ writable: false
+ });
+ Object.defineProperty(self, "id", {
+ value: id,
+ writable: false
+ });
+ Object.defineProperty(self, "type", {
+ value: className,
+ writable: false
+ });
+
+ className = className.toLowerCase();
+ Object.defineProperty(self, "getPluginName", {
+ writable: false,
+ value: function() {
+ return this.map.getId() + "-" + className.toLowerCase();
+ }
+ });
+};
+
+utils.extend(Overlay, BaseClass);
+
+
+Overlay.prototype.exec = function() {
+ this._cmdQueue.push.call(this._cmdQueue, {
+ target: this,
+ args: Array.prototype.slice.call(arguments, 0)
+ });
+};
+Overlay.prototype.getId = function() {
+ return this.id;
+};
+Overlay.prototype.getMap = function() {
+ return this.map;
+};
+Overlay.prototype.getHashCode = function() {
+ return this.hashCode;
+};
+
+module.exports = Overlay;

Implementing virtual synchronizing mechanism