Commit 20c7c5ef authored by Piotr Gawron's avatar Piotr Gawron
Browse files

AbstractMarker can have a set of icons (in such case generic icon is...

AbstractMarker can have a set of icons (in such case generic icon is presented). There is single marker per element on the map
parent fd662f5a
......@@ -16,6 +16,7 @@ function AbstractMarker(params) {
// call super constructor
ObjectWithListeners.call(this);
self._icons = [];
self.setIdentifiedElement(params.element);
self.setIcon(params.element.getIcon());
self.setCustomMap(params.map);
......@@ -48,18 +49,81 @@ AbstractMarker.prototype.getId = function () {
/**
* Returns icon of the marker.
*
* @returns icon of the marker
* @returns string/undefined identifying icon of the marker
*/
AbstractMarker.prototype.getIcon = function () {
return this._icon;
var icons = this._icons;
if (icons.length === 0) {
return undefined;
} else if (icons.length === 1) {
return icons[0];
} else {
return "marker/generic/search_green.png";
}
};
AbstractMarker.prototype.setIcon = function (icon) {
AbstractMarker.prototype._updateIcon = function () {
var self = this;
self._icon = icon;
var googleMarker = self.getGoogleMarker();
if (googleMarker !== undefined) {
googleMarker.setIcon(GuiConnector.getImgPrefix() + self.getIcon());
if (self.getIcon() === undefined) {
self.hide();
} else {
googleMarker.setIcon(GuiConnector.getImgPrefix() + self.getIcon());
if (googleMarker.getMap() === null) {
self.show();
}
}
}
};
AbstractMarker.prototype.setIcon = function (icon) {
var self = this;
if (icon === null || icon === undefined) {
self._icons = [];
} else {
self._icons = [icon];
}
self._updateIcon(self);
};
AbstractMarker.prototype.setIcons = function (icons) {
var self = this;
self._icons = icons;
self._updateIcon(self);
};
AbstractMarker.prototype.addIcon = function (icon) {
var self = this;
self._icons.push(icon);
self._updateIcon(self);
};
AbstractMarker.prototype.addIcons = function (icons) {
var self = this;
for (var i = 0; i < icons.length; i++) {
self._icons.push(icons[i]);
}
self._updateIcon(self);
};
AbstractMarker.prototype.removeIcons = function (icons) {
var self = this;
for (var i = 0; i < icons.length; i++) {
self.removeIcon(icons[i], true);
}
self._updateIcon(self);
};
AbstractMarker.prototype.removeIcon = function (icon, preventMarkerUpdate) {
var self = this;
var index = self._icons.indexOf(icon);
if (index > -1) {
self._icons.splice(index, 1);
if (!preventMarkerUpdate) {
self._updateIcon(self);
}
} else {
logger.warn("Unknown icon for marker: ", icon);
}
};
......@@ -89,6 +153,13 @@ AbstractMarker.prototype.hide = function () {
}
};
AbstractMarker.prototype.isShown = function () {
if (this.getGoogleMarker() === undefined) {
return false;
}
return (this.getGoogleMarker().getMap() !== undefined && this.getGoogleMarker().getMap() !== null);
};
/**
* Returns {@link AbstractCustomMap} where marker is located.
*
......@@ -186,10 +257,6 @@ AbstractMarker.prototype.getIdentifiedElement = function () {
return this._identifiedElement;
};
AbstractMarker.prototype.updateIdentifiedElement = function (identifiedElement) {
this.setIcon(identifiedElement.getIcon());
};
AbstractMarker.prototype.setIdentifiedElement = function (identifiedElement) {
this._identifiedElement = identifiedElement;
};
......
......@@ -20,12 +20,9 @@ function MarkerSurfaceCollection(params) {
var self = this;
ObjectWithListeners.call(this);
self._markerOverlaysPerType = {
ALIAS: [],
REACTION: [],
POINT: []
};
self._surfaceOverlaysPerType = {
self._overlayIcons = {};
self._markers = {};
self._overlaySurfaces = {
ALIAS: [],
REACTION: [],
POINT: []
......@@ -50,29 +47,25 @@ MarkerSurfaceCollection.prototype.getMap = function () {
MarkerSurfaceCollection.prototype.refreshOverlayMarkers = function (overlay) {
var self = this;
var markerOverlaysPerType = self._markerOverlaysPerType;
for (var markerType in markerOverlaysPerType) {
if (markerOverlaysPerType.hasOwnProperty(markerType)) {
var markers = markerOverlaysPerType[markerType][overlay.getName()];
if (markers !== undefined) {
for (var key in markers) {
if (markers.hasOwnProperty(key)) {
var marker = markers[key];
marker.hide();
marker.show();
}
}
}
var overlayData = self._overlayIcons[overlay.getName()];
for (var elementId in overlayData) {
if (overlayData.hasOwnProperty(elementId)) {
var marker = self._markers[elementId];
marker.hide();
marker.show();
}
}
};
MarkerSurfaceCollection.prototype.createMarkerForDbOverlay = function (element, dbOverlay) {
MarkerSurfaceCollection.prototype.addMarker = function (params) {
var element = params.element;
var icons = params.icons;
var self = this;
var result = self.getMarker({element: element, overlay: dbOverlay});
var result = self.getMarker(element);
if (result !== undefined) {
result.updateIdentifiedElement(element);
result.addIcons(icons);
return Promise.resolve(result);
}
......@@ -95,12 +88,24 @@ MarkerSurfaceCollection.prototype.createMarkerForDbOverlay = function (element,
return self.getMap().callListeners("onBioEntityClick", element);
}]
});
result.setIcons(icons);
return result.init().then(function () {
self.putMarker({element: element, overlay: dbOverlay}, result);
self.putMarker(element, result);
return result;
});
};
MarkerSurfaceCollection.prototype.removeMarker = function (params) {
var element = params.element;
var icons = params.icons;
var self = this;
var result = self.getMarker(element);
result.removeIcons(icons);
};
MarkerSurfaceCollection.prototype.createSurfaceForDbOverlay = function (element, dbOverlay) {
var self = this;
......@@ -149,35 +154,14 @@ MarkerSurfaceCollection.prototype.createSurfaceForDbOverlay = function (element,
};
MarkerSurfaceCollection.prototype.getMarker = function (params) {
var element = new IdentifiedElement(params.element);
var overlay = params.overlay;
var markerOverlaysPerType = this._markerOverlaysPerType;
var overlayMarkers = markerOverlaysPerType[element.getType()][overlay.getName()];
if (overlayMarkers === undefined) {
markerOverlaysPerType[element.getType()][overlay.getName()] = [];
overlayMarkers = markerOverlaysPerType[element.getType()][overlay.getName()];
}
return overlayMarkers[element.getId()];
};
MarkerSurfaceCollection.prototype.getMarkers = function () {
var result = [];
var markerOverlaysPerType = this._markerOverlaysPerType;
for (var markerType in markerOverlaysPerType) {
if (markerOverlaysPerType.hasOwnProperty(markerType)) {
var markersByType = markerOverlaysPerType[markerType];
for (var overlayName in markersByType) {
if (markersByType.hasOwnProperty(overlayName)) {
var markers = markersByType[overlayName];
for (var key in markers) {
if (markers.hasOwnProperty(key)) {
result.push(markers[key]);
}
}
}
var markers = this._markers;
for (var key in markers) {
if (markers.hasOwnProperty(key)) {
var marker = markers[key];
if (marker.isShown()) {
result.push(marker);
}
}
}
......@@ -187,18 +171,13 @@ MarkerSurfaceCollection.prototype.getMarkers = function () {
MarkerSurfaceCollection.prototype.getSurfaces = function () {
var result = [];
var surfaceOverlaysPerType = this._surfaceOverlaysPerType;
for (var markerType in surfaceOverlaysPerType) {
if (surfaceOverlaysPerType.hasOwnProperty(markerType)) {
var markersByType = surfaceOverlaysPerType[markerType];
for (var overlayName in markersByType) {
if (markersByType.hasOwnProperty(overlayName)) {
var markers = markersByType[overlayName];
for (var key in markers) {
if (markers.hasOwnProperty(key)) {
result.push(markers[key]);
}
}
var overlaySurfaces = this._overlaySurfaces;
for (var overlayName in overlaySurfaces) {
if (overlaySurfaces.hasOwnProperty(overlayName)) {
var surfaces = overlaySurfaces[overlayName];
for (var key in surfaces) {
if (surfaces.hasOwnProperty(key)) {
result.push(surfaces[key]);
}
}
}
......@@ -207,51 +186,39 @@ MarkerSurfaceCollection.prototype.getSurfaces = function () {
return result;
};
MarkerSurfaceCollection.prototype.putMarker = function (params, marker) {
var element = new IdentifiedElement(params.element);
var overlay = params.overlay;
MarkerSurfaceCollection.prototype.getMarker = function (element) {
return this._markers[new IdentifiedElement(element).toString()];
};
var markerOverlaysPerType = this._markerOverlaysPerType;
var overlayMarkers = markerOverlaysPerType[element.getType()][overlay.getName()];
if (overlayMarkers === undefined) {
markerOverlaysPerType[element.getType()][overlay.getName()] = [];
overlayMarkers = markerOverlaysPerType[element.getType()][overlay.getName()];
}
overlayMarkers[element.getId()] = marker;
MarkerSurfaceCollection.prototype.putMarker = function (element, marker) {
this._markers[new IdentifiedElement(element).toString()] = marker;
};
MarkerSurfaceCollection.prototype.getSurface = function (params) {
var element = new IdentifiedElement(params.element);
var overlay = params.overlay;
var surfaceOverlaysPerType = this._surfaceOverlaysPerType;
var overlaySurfaces = surfaceOverlaysPerType[element.getType()][overlay.getName()];
var overlaySurfaces = this._overlaySurfaces[overlay.getName()];
if (overlaySurfaces === undefined) {
surfaceOverlaysPerType[element.getType()][overlay.getName()] = [];
overlaySurfaces = surfaceOverlaysPerType[element.getType()][overlay.getName()];
this._overlaySurfaces[overlay.getName()] = [];
overlaySurfaces = this._overlaySurfaces[overlay.getName()];
}
return overlaySurfaces[element.getId()];
return overlaySurfaces[element.toString()];
};
MarkerSurfaceCollection.prototype.putSurface = function (params, surface) {
var element = new IdentifiedElement(params.element);
var overlay = params.overlay;
var surfaceOverlaysPerType = this._surfaceOverlaysPerType;
var overlaySurfaces = surfaceOverlaysPerType[element.getType()][overlay.getName()];
var overlaySurfaces = this._overlaySurfaces[overlay.getName()];
if (overlaySurfaces === undefined) {
surfaceOverlaysPerType[element.getType()][overlay.getName()] = [];
overlaySurfaces = surfaceOverlaysPerType[element.getType()][overlay.getName()];
this._overlaySurfaces[overlay.getName()] = [];
overlaySurfaces = this._overlaySurfaces[overlay.getName()];
}
overlaySurfaces[element.getId()] = surface;
overlaySurfaces[element.toString()] = surface;
};
MarkerSurfaceCollection.prototype.removeUnmodifiedMarkersAndSurfaces = function (modifiedMarkersAndSurfaces, dbOverlay) {
var modifiedMarkers = {
"ALIAS": [],
"REACTION": [],
"POINT": []
};
MarkerSurfaceCollection.prototype.removeUnmodifiedSurfaces = function (modifiedMarkersAndSurfaces, dbOverlay) {
var modifiedSurfaces = {
"ALIAS": [],
"REACTION": [],
......@@ -262,37 +229,19 @@ MarkerSurfaceCollection.prototype.removeUnmodifiedMarkersAndSurfaces = function
var object = modifiedMarkersAndSurfaces[i];
var identifiedElement = object.getIdentifiedElement();
if (object instanceof AbstractSurfaceElement) {
modifiedSurfaces[identifiedElement.getType()][identifiedElement.getId()] = true;
} else if (object instanceof AbstractMarker) {
modifiedMarkers[identifiedElement.getType()][identifiedElement.getId()] = true;
modifiedSurfaces[identifiedElement.toString()] = true;
} else {
throw new Error("Unknown class type: " + object.prototype.name);
}
}
var markerType, key;
var markerOverlaysPerType = this._markerOverlaysPerType;
for (markerType in markerOverlaysPerType) {
if (markerOverlaysPerType.hasOwnProperty(markerType)) {
var markers = markerOverlaysPerType[markerType][dbOverlay.getName()];
for (key in markers) {
if (markers.hasOwnProperty(key) && !modifiedMarkers[markerType][key]) {
markers[key].setMap(null);
delete markers[key];
}
}
}
}
var surfaceOverlaysPerType = this._surfaceOverlaysPerType;
for (markerType in surfaceOverlaysPerType) {
if (surfaceOverlaysPerType.hasOwnProperty(markerType)) {
var mapOverlays = surfaceOverlaysPerType[markerType][dbOverlay.getName()];
for (key in mapOverlays) {
if (mapOverlays.hasOwnProperty(key) && !modifiedSurfaces[markerType][key]) {
mapOverlays[key].setMap(null);
delete mapOverlays[key];
}
var surfaceOverlaysPerType = this._overlaySurfaces[dbOverlay.getName()];
for (var key in surfaceOverlaysPerType) {
if (surfaceOverlaysPerType.hasOwnProperty(key)) {
var mapOverlay = surfaceOverlaysPerType[key];
if (!modifiedSurfaces[key]) {
surfaceOverlaysPerType[key].setMap(null);
delete surfaceOverlaysPerType[key];
}
}
}
......@@ -300,32 +249,146 @@ MarkerSurfaceCollection.prototype.removeUnmodifiedMarkersAndSurfaces = function
MarkerSurfaceCollection.prototype.renderOverlay = function (allElements, overlay) {
var self = this;
var elements = [];
var markerElements = [];
var surfaceElements = [];
for (var i = 0; i < allElements.length; i++) {
if (allElements[i].getModelId() === self.getMap().getId()) {
elements.push(allElements[i]);
var element = allElements[i];
if (element.getModelId() === self.getMap().getId()) {
if (element.getIcon() !== null && element.getIcon() !== undefined) {
markerElements.push(element);
} else {
surfaceElements.push(element);
}
}
}
var markers;
return self.renderOverlayMarkers(markerElements, overlay).then(function (result) {
markers = result;
return self.renderOverlaySurfaces(surfaceElements, overlay);
}).then(function (surfaces) {
return markers.concat(surfaces);
});
};
function IconDifference(element) {
this.element = element;
this.iconsToAdd = [];
this.iconsToRemove = [];
}
IconDifference.prototype.addIcon = function (icon) {
var index = this.iconsToRemove.indexOf(icon);
if (index > -1) {
this.iconsToRemove.splice(index, 1);
} else {
this.iconsToAdd.push(icon);
}
};
IconDifference.prototype.removeIcon = function (icon) {
var index = this.iconsToAdd.indexOf(icon);
if (index > -1) {
this.iconsToAdd.splice(index, 1);
} else {
this.iconsToRemove.push(icon);
}
};
IconDifference.prototype.removeIcons = function (icons) {
for (var i = 0; i < icons.length; i++) {
this.removeIcon(icons[i]);
}
};
MarkerSurfaceCollection.prototype.renderOverlayMarkers = function (elements, overlay) {
var self = this;
var markers = [];
//first get full data about all elements in one go (not one-by-one queries)
return self.getMap().getModel().getByIdentifiedElements(elements).then(function () {
return Promise.each(elements, function (element) {
var icon = element.getIcon();
if (icon !== null && icon !== undefined) {
return self.createMarkerForDbOverlay(element, overlay).then(function (marker) {
markers.push(marker);
});
} else {
return self.createSurfaceForDbOverlay(element, overlay).then(function (mapOverlay) {
markers.push(mapOverlay);
});
var elementsToProcess = [];
var i, element, icon, data, entry, key;
for (i = 0; i < elements.length; i++) {
element = elements[i];
icon = element.getIcon();
data = elementsToProcess[element.toString()];
if (data === undefined) {
elementsToProcess[element.toString()] = new IconDifference(element);
data = elementsToProcess[element.toString()]
}
data.addIcon(icon);
}
var iconData = self.getOverlayIconData(overlay);
for (key in iconData) {
if (iconData.hasOwnProperty(key)) {
entry = iconData[key];
element = entry.element;
data = elementsToProcess[element.toString()];
if (data === undefined) {
elementsToProcess[element.toString()] = new IconDifference(element);
data = elementsToProcess[element.toString()]
}
data.removeIcons(entry.icons);
}
}
});
var promises = [];
for (key in elementsToProcess) {
if (elementsToProcess.hasOwnProperty(key)) {
data = elementsToProcess[key];
if (data.iconsToAdd.length > 0) {
promises.push(self.addMarker({element: data.element, icons: data.iconsToAdd}).then(function (marker) {
markers.push(marker);
}));
}
if (data.iconsToRemove.length > 0) {
promises.push(self.removeMarker({element: data.element, icons: data.iconsToRemove}));
}
}
}
return Promise.all(promises);
}).then(function () {
self.removeUnmodifiedMarkersAndSurfaces(markers, overlay);
self.createOverlayIconData(elements, overlay);
return markers;
});
};
MarkerSurfaceCollection.prototype.getOverlayIconData = function (overlay) {
var iconData = this._overlayIcons[overlay.getName()];
if (iconData === undefined) {
this._overlayIcons[overlay.getName()] = {};
iconData = this._overlayIcons[overlay.getName()]
}
return iconData;
};
MarkerSurfaceCollection.prototype.createOverlayIconData = function (elements, overlay) {
var iconData = {};
for (var i = 0; i < elements.length; i++) {
var element = elements[i];
if (iconData[element.toString()] === undefined) {
iconData[element.toString()] = {icons: [], element: element};
}
iconData[element.toString()].icons.push(element.getIcon());
}
this._overlayIcons[overlay.getName()] = iconData;
};
MarkerSurfaceCollection.prototype.renderOverlaySurfaces = function (elements, overlay) {
var self = this;
var surfaces = [];
return self.getMap().getModel().getByIdentifiedElements(elements).then(function () {
return Promise.each(elements, function (element) {
return self.createSurfaceForDbOverlay(element, overlay).then(function (mapOverlay) {
surfaces.push(mapOverlay);
});
});
}).then(function () {
self.removeUnmodifiedSurfaces(surfaces, overlay);
return surfaces;
});
};
module.exports = MarkerSurfaceCollection;
......@@ -279,28 +279,23 @@ describe('CustomMap', function () {
map.getModel().addAlias(alias);
map.getModel().addReaction(reaction);
var identifiedElement = new IdentifiedElement(alias);
identifiedElement.setIcon("empty.png");
var identifiedElement2 = new IdentifiedElement(alias);
identifiedElement2.setIcon("new_icon.png");
var marker;
var oc = helper.createDbOverlay(map);
oc.getIdentifiedElements = function () {
return Promise.resolve([new IdentifiedElement({
objectId: alias.getId(),
icon: "empty.png",
modelId: map.getId(),
type: "Alias"
}), new IdentifiedElement(reaction)]);
return Promise.resolve([identifiedElement, new IdentifiedElement(reaction)]);
};
return map.renderOverlayCollection({
overlayCollection: oc
}).then(function () {
marker = map.getMarkerSurfaceCollection().getMarker({element: alias, overlay: oc});
marker = map.getMarkerSurfaceCollection().getMarker(identifiedElement);
oc.getIdentifiedElements = function () {
return Promise.resolve([new IdentifiedElement({
objectId: alias.getId(),
icon: "new_icon.png",
<