diff --git a/Makefile b/Makefile
index 000889bc29..7d8934de3d 100644
--- a/Makefile
+++ b/Makefile
@@ -28,7 +28,7 @@ build/ol3.js: $(SRC)
( echo "goog.require('goog.dom');" ; find src/ol -name \*.js | xargs grep -rh ^goog.provide | sort | uniq | sed -e 's/provide/require/g' ) > $@
.PHONY: demos
-demos: demos/api1 demos/proj4js demos/side-by-side
+demos: demos/api1 demos/proj4js demos/side-by-side demos/two-layers
.PHONY: demos/api1
demos/api1: \
@@ -84,6 +84,36 @@ demos/side-by-side/simple-optimizations.js: $(PLOVR_JAR) $(SRC) base.json \
@echo $@ "uncompressed:" $$(wc -c <$@) bytes
@echo $@ " compressed:" $$(gzip -9 -c <$@ | wc -c) bytes
+.PHONY: demos/two-layers
+demos/two-layers: \
+ demos/two-layers/advanced-optimizations.html \
+ demos/two-layers/advanced-optimizations.js \
+ demos/two-layers/debug.html \
+ demos/two-layers/simple-optimizations.html \
+ demos/two-layers/simple-optimizations.js
+
+demos/two-layers/advanced-optimizations.html: demos/two-layers/index.html.in
+ sed -e 's|@SRC@|advanced-optimizations.js|' $< > $@
+
+demos/two-layers/advanced-optimizations.js: $(PLOVR_JAR) $(SRC) base.json \
+ demos/two-layers/two-layers.json demos/two-layers/two-layers.js
+ java -jar $(PLOVR_JAR) build demos/two-layers/two-layers.json >$@
+ @echo $@ "uncompressed:" $$(wc -c <$@) bytes
+ @echo $@ " compressed:" $$(gzip -9 -c <$@ | wc -c) bytes
+
+demos/two-layers/debug.html: demos/two-layers/index.html.in
+ sed -e 's|@SRC@|http://localhost:9810/compile?id=demo-two-layers|' $< > $@
+
+demos/two-layers/simple-optimizations.html: demos/two-layers/index.html.in
+ sed -e 's|@SRC@|simple-optimizations.js|' $< > $@
+
+# FIXME invoke plovr directly, rather than assuming that the server is running
+demos/two-layers/simple-optimizations.js: $(PLOVR_JAR) $(SRC) base.json \
+ demos/two-layers/two-layers.json demos/two-layers/two-layers.js
+ curl 'http://localhost:9810/compile?id=demo-two-layers&mode=SIMPLE' > $@
+ @echo $@ "uncompressed:" $$(wc -c <$@) bytes
+ @echo $@ " compressed:" $$(gzip -9 -c <$@ | wc -c) bytes
+
.PHONY: serve
serve: $(PLOVR_JAR)
java -jar $(PLOVR_JAR) serve build/ol3.json build/ol3-api.json demos/*/*.json
diff --git a/demos/two-layers/index.html.in b/demos/two-layers/index.html.in
new file mode 100644
index 0000000000..96c1c5922b
--- /dev/null
+++ b/demos/two-layers/index.html.in
@@ -0,0 +1,32 @@
+
+
+
+
+ ol3 two-layers demo
+
+
+ ol3 two-layers demo
+
+
+ | DOM |
+ WebGL |
+
+
+ Coming soon... |
+ |
+
+
+ |
+
+ |
+
+
+
+
+
diff --git a/demos/two-layers/two-layers.js b/demos/two-layers/two-layers.js
new file mode 100644
index 0000000000..5daf7010ba
--- /dev/null
+++ b/demos/two-layers/two-layers.js
@@ -0,0 +1,57 @@
+goog.require('ol.Coordinate');
+goog.require('ol.RendererHint');
+goog.require('ol.control.Attribution');
+goog.require('ol.createMap');
+goog.require('ol.layer.BingMaps');
+goog.require('ol.layer.TileJSON');
+
+
+/**
+ * FIXME The DOM renderer doesn't support partially-loaded layers yet
+ * FIXME Remove this define when it does
+ * @define {boolean} Enable DOM map.
+ */
+ol.TWO_LAYERS_DEMO_ENABLE_DOM = false;
+
+
+var layer1 = new ol.layer.BingMaps(
+ ol.BingMapsStyle.AERIAL,
+ 'AheP841R-MsLErKQChaTba_xDoOCl40-EeTubD9uNhNAyQTePwFY9iVD1_pyqqlE');
+var layer2 = new ol.layer.TileJSON(
+ 'http://api.tiles.mapbox.com/v3/mapbox.va-quake-aug.jsonp');
+
+var layers = new ol.Collection([layer1, layer2]);
+
+var webglMap = ol.createMap(
+ document.getElementById('webglMap'),
+ {'layers': new ol.Collection([layer1, layer2])},
+ ol.RendererHint.WEBGL);
+
+goog.events.listen(layer2, goog.events.EventType.LOAD, function() {
+ webglMap.setUserCenter(new ol.Coordinate(-77.93254999999999, 37.9555));
+ webglMap.setResolution(layer2.getStore().getResolutions()[5]);
+});
+
+var domMap;
+if (ol.TWO_LAYERS_DEMO_ENABLE_DOM) {
+ domMap = ol.createMap(
+ document.getElementById('domMap'),
+ {'layers': layers},
+ ol.RendererHint.DOM);
+ domMap.bindTo('center', webglMap);
+ domMap.bindTo('layers', webglMap);
+ domMap.bindTo('resolution', webglMap);
+ domMap.bindTo('rotation', webglMap);
+} else {
+ domMap = null;
+}
+
+var attributionControl = new ol.control.Attribution(webglMap);
+document.getElementById('attribution').appendChild(
+ attributionControl.getElement());
+
+goog.exportSymbol('layer1', layer1);
+goog.exportSymbol('layer2', layer2);
+goog.exportSymbol('layers', layers);
+goog.exportSymbol('domMap', domMap);
+goog.exportSymbol('webglMap', webglMap);
diff --git a/demos/two-layers/two-layers.json b/demos/two-layers/two-layers.json
new file mode 100644
index 0000000000..722701e841
--- /dev/null
+++ b/demos/two-layers/two-layers.json
@@ -0,0 +1,9 @@
+{
+
+ "id": "demo-two-layers",
+
+ "inherits": "../../base.json",
+
+ "inputs": "demos/two-layers/two-layers.js"
+
+}
diff --git a/src/ol/base/collection_test.js b/src/ol/base/collection_test.js
index 26dff88534..020cbdfa7d 100644
--- a/src/ol/base/collection_test.js
+++ b/src/ol/base/collection_test.js
@@ -163,34 +163,34 @@ function testCreateFromCollection() {
function testLengthChangeInsertAt() {
var collection = ol.Collection.create([0, 1, 2]);
- var lengthChangedCalled;
- collection.length_changed = function() {
- lengthChangedCalled = true;
- };
+ var lengthEventDispatched;
+ goog.events.listen(collection, 'length_changed', function() {
+ lengthEventDispatched = true;
+ });
collection.insertAt(2, 3);
- assertTrue(lengthChangedCalled);
+ assertTrue(lengthEventDispatched);
}
function testLengthChangeRemoveAt() {
var collection = ol.Collection.create([0, 1, 2]);
- var lengthChangedCalled;
- collection.length_changed = function() {
- lengthChangedCalled = true;
- };
+ var lengthEventDispatched;
+ goog.events.listen(collection, 'length_changed', function() {
+ lengthEventDispatched = true;
+ });
collection.removeAt(0);
- assertTrue(lengthChangedCalled);
+ assertTrue(lengthEventDispatched);
}
function testLengthChangeSetAt() {
var collection = ol.Collection.create([0, 1, 2]);
- var lengthChangedCalled;
- collection.length_changed = function() {
- lengthChangedCalled = true;
- };
+ var lengthEventDispatched;
+ goog.events.listen(collection, 'length_changed', function() {
+ lengthEventDispatched = true;
+ });
collection.setAt(1, 1);
- assertUndefined(lengthChangedCalled);
+ assertUndefined(lengthEventDispatched);
}
diff --git a/src/ol/base/map.js b/src/ol/base/map.js
index 94c2578664..1b18c325d9 100644
--- a/src/ol/base/map.js
+++ b/src/ol/base/map.js
@@ -733,7 +733,7 @@ ol.Map.prototype.updateMatrices_ = function() {
1);
if (this.canRotate() && goog.isDef(rotation)) {
goog.vec.Mat4.rotate(this.coordinateToPixelMatrix_,
- rotation,
+ -rotation,
0,
0,
1);
@@ -743,26 +743,9 @@ ol.Map.prototype.updateMatrices_ = function() {
-center.y,
0);
- goog.vec.Mat4.makeIdentity(this.pixelToCoordinateMatrix_);
- goog.vec.Mat4.translate(this.pixelToCoordinateMatrix_,
- center.x,
- center.y,
- 0);
- if (this.canRotate() && goog.isDef(rotation)) {
- goog.vec.Mat4.rotate(this.coordinateToPixelMatrix_,
- -rotation,
- 0,
- 0,
- 1);
- }
- goog.vec.Mat4.scale(this.pixelToCoordinateMatrix_,
- resolution,
- -resolution,
- 1);
- goog.vec.Mat4.translate(this.pixelToCoordinateMatrix_,
- -size.width / 2,
- -size.height / 2,
- 0);
+ var inverted = goog.vec.Mat4.invert(
+ this.coordinateToPixelMatrix_, this.pixelToCoordinateMatrix_);
+ goog.asserts.assert(inverted);
this.matriciesDirty_ = false;
diff --git a/src/ol/base/object.js b/src/ol/base/object.js
index 6518c89b83..e3555d3332 100644
--- a/src/ol/base/object.js
+++ b/src/ol/base/object.js
@@ -95,23 +95,6 @@ ol.Object.getGetterName = function(key) {
};
-/**
- * @private
- * @type {Object.}
- */
-ol.Object.changedMethodNameCache_ = {};
-
-
-/**
- * @param {string} key String.
- * @return {string} Changed method name.
- */
-ol.Object.getChangedMethodName = function(key) {
- return ol.Object.changedMethodNameCache_[key] ||
- (ol.Object.changedMethodNameCache_[key] = key + '_changed');
-};
-
-
/**
* @private
* @type {Object.}
@@ -222,12 +205,6 @@ ol.Object.prototype.notify = function(key) {
* @private
*/
ol.Object.prototype.notifyInternal_ = function(key) {
- var changedMethodName = ol.Object.getChangedMethodName(key);
- if (this[changedMethodName]) {
- this[changedMethodName]();
- } else {
- this.changed(key);
- }
var eventType = ol.Object.getChangedEventType(key);
this.dispatchEvent(eventType);
};
diff --git a/src/ol/base/object_test.js b/src/ol/base/object_test.js
index 28b0339535..e93185f08d 100644
--- a/src/ol/base/object_test.js
+++ b/src/ol/base/object_test.js
@@ -32,27 +32,6 @@ function testSetValues() {
assertEquals(2, m.get('k2'));
}
-function testNotifyCallback() {
- var m = new ol.Object();
- var callbackCalled;
- m.changed = function() {
- callbackCalled = true;
- };
- m.notify('k');
- assertTrue(callbackCalled);
-}
-
-
-function testNotifyKeyCallback() {
- var m = new ol.Object();
- var callbackCalled = false;
- m.k_changed = function() {
- callbackCalled = true;
- };
- m.notify('k');
- assertTrue(callbackCalled);
-}
-
function testNotifyKeyEvent() {
var m = new ol.Object();
@@ -65,38 +44,16 @@ function testNotifyKeyEvent() {
}
-function testSetNotifyCallback() {
- var m = new ol.Object();
- var callbackCalled;
- m.changed = function() {
- callbackCalled = true;
- };
- m.set('k', 1);
- assertTrue(callbackCalled);
-}
-
-
-function testSetNotifyKeyCallback() {
- var m = new ol.Object();
- var callbackCalled = false;
- m.k_changed = function(v) {
- callbackCalled = true;
- };
- m.set('k', 1);
- assertTrue(callbackCalled);
-}
-
-
-function testBindSetNotifyKeyCallback() {
+function testBindSetNotifyKeyEvent() {
var m = new ol.Object();
var n = new ol.Object();
var callbackCalled = false;
- n.k_changed = function(v) {
- callbackCalled = true;
- };
+ goog.events.listen(n, 'k_changed', function() {
+ eventDispatched = true;
+ });
n.bindTo('k', m);
m.set('k', 1);
- assertTrue(callbackCalled);
+ assertTrue(eventDispatched);
}
@@ -189,17 +146,17 @@ function testBindNotify() {
var m = new ol.Object();
var n = new ol.Object();
m.bindTo('k', n);
- mCallbackCalled = false;
- m.k_changed = function() {
- mCallbackCalled = true;
- };
- nCallbackCalled = false;
- n.k_changed = function() {
- nCallbackCalled = true;
- };
+ mEventDispatched = false;
+ goog.events.listen(m, 'k_changed', function() {
+ mEventDispatched = true;
+ });
+ nEventDispatched = false;
+ goog.events.listen(n, 'k_changed', function() {
+ nEventDispatched = true;
+ });
n.set('k', 1);
- assertTrue(mCallbackCalled);
- assertTrue(nCallbackCalled);
+ assertTrue(mEventDispatched);
+ assertTrue(nEventDispatched);
}
@@ -207,17 +164,17 @@ function testBindBackwardsNotify() {
var m = new ol.Object();
var n = new ol.Object();
n.bindTo('k', m);
- mCallbackCalled = false;
- m.k_changed = function() {
- mCallbackCalled = true;
- };
- nCallbackCalled = false;
- n.k_changed = function() {
- nCallbackCalled = true;
- };
+ mEventDispatched = false;
+ goog.events.listen(m, 'k_changed', function() {
+ mEventDispatched = true;
+ });
+ nEventDispatched = false;
+ goog.events.listen(n, 'k_changed', function() {
+ nEventDispatched = true;
+ });
n.set('k', 1);
- assertTrue(mCallbackCalled);
- assertTrue(nCallbackCalled);
+ assertTrue(mEventDispatched);
+ assertTrue(nEventDispatched);
}
@@ -231,23 +188,23 @@ function testBindRename() {
}
-function testBindRenameCallbacks() {
+function testBindRenameEvents() {
var m = new ol.Object();
var n = new ol.Object();
- var kmCallbackCalled = false;
- m.km_changed = function() {
- kmCallbackCalled = true;
- };
- var knCallbackCalled = false;
- n.kn_changed = function() {
- knCallbackCalled = true;
- };
+ kmEventDispatched = false;
+ goog.events.listen(m, 'km_changed', function() {
+ kmEventDispatched = true;
+ });
+ knEventDispatched = false;
+ goog.events.listen(n, 'kn_changed', function() {
+ knEventDispatched = true;
+ });
n.bindTo('kn', m, 'km');
m.set('km', 1);
assertEquals(m.get('km'), 1);
assertEquals(n.get('kn'), 1);
- assertTrue(kmCallbackCalled);
- assertTrue(knCallbackCalled);
+ assertTrue(kmEventDispatched);
+ assertTrue(knEventDispatched);
}
@@ -277,20 +234,6 @@ function testTransitiveBindBackwards() {
}
-function testInheritance() {
- var C = function() {};
- C.prototype = new ol.Object();
- var callbackCalled;
- C.prototype.k_changed = function() {
- callbackCalled = true;
- };
- var c = new C();
- c.set('k', 1);
- assertEquals(1, c.get('k'));
- assertTrue(callbackCalled);
-}
-
-
function testMrideyAccessors() {
// http://blog.mridey.com/2010/03/maps-javascript-api-v3-more-about.html
var a = new ol.Object();
@@ -424,20 +367,9 @@ function testBindSelf() {
}
-function testChangedKey() {
- var a = new ol.Object();
- var changedKey;
- a.changed = function(key) {
- changedKey = key;
- };
- a.set('k', 1);
- assertEquals('k', changedKey);
-}
-
-
function testCreateFromObject() {
var obj = {k: 1};
- var obj = ol.Object.create(obj);
+ obj = ol.Object.create(obj);
assertTrue(obj instanceof ol.Object);
assertEquals(1, obj.get('k'));
}
@@ -458,14 +390,6 @@ function testCreateWithOptions() {
function testEventTypeCaseSensitivity() {
var obj = new ol.Object();
- var lowercaseChangedMethodCalled = false;
- obj.k_changed = function() {
- lowercaseChangedMethodCalled = true;
- };
- var uppercaseChangedMethodCalled = false;
- obj.K_changed = function() {
- uppercaseChangedMethodCalled = true;
- };
var lowercaseEventDispatched = false;
goog.events.listen(obj, 'k_changed', function() {
lowercaseEventDispatched = true;
@@ -477,6 +401,4 @@ function testEventTypeCaseSensitivity() {
obj.set('K', 1);
assertTrue(lowercaseEventDispatched);
assertFalse(uppercaseEventDispatched);
- assertFalse(lowercaseChangedMethodCalled);
- assertTrue(uppercaseChangedMethodCalled);
}
diff --git a/src/ol/control/attribution.js b/src/ol/control/attribution.js
index 1b45e36ef2..8157301ff1 100644
--- a/src/ol/control/attribution.js
+++ b/src/ol/control/attribution.js
@@ -116,6 +116,7 @@ ol.control.Attribution.prototype.createAttributionElementsForLayer_ =
if (!map.isDef ||
!layerVisible ||
+ goog.isNull(attributionVisibilities) ||
!attributionVisibilities[attributionKey]) {
goog.style.showElement(attributionElement, false);
}
diff --git a/src/ol/webgl/tilelayerrenderer.js b/src/ol/webgl/tilelayerrenderer.js
index bf2ff8bfc9..65b39c0ded 100644
--- a/src/ol/webgl/tilelayerrenderer.js
+++ b/src/ol/webgl/tilelayerrenderer.js
@@ -176,9 +176,9 @@ ol.webgl.TileLayerRenderer.prototype.bindFramebuffer_ =
var texture = gl.createTexture();
gl.bindTexture(goog.webgl.TEXTURE_2D, texture);
- gl.texImage2D(goog.webgl.TEXTURE_2D, 0, gl.RGBA, framebufferDimension,
- framebufferDimension, 0, goog.webgl.RGBA, goog.webgl.UNSIGNED_BYTE,
- null);
+ gl.texImage2D(goog.webgl.TEXTURE_2D, 0, goog.webgl.RGBA,
+ framebufferDimension, framebufferDimension, 0, goog.webgl.RGBA,
+ goog.webgl.UNSIGNED_BYTE, null);
gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MAG_FILTER,
goog.webgl.LINEAR);
gl.texParameteri(goog.webgl.TEXTURE_2D, goog.webgl.TEXTURE_MIN_FILTER,