[Commits] r1326 - in sandbox/camptocamp/geobretagne: lib/GeoExt/data lib/GeoExt/widgets tests/lib/GeoExt/data tests/lib/GeoExt/widgets
commits at geoext.org
commits at geoext.org
Tue Aug 11 16:51:54 CEST 2009
Author: elemoine
Date: 2009-08-11 16:51:54 +0200 (Tue, 11 Aug 2009)
New Revision: 1326
Modified:
sandbox/camptocamp/geobretagne/lib/GeoExt/data/FeatureReader.js
sandbox/camptocamp/geobretagne/lib/GeoExt/data/FeatureStore.js
sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendPanel.js
sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendWMS.js
sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/FeatureStore.html
sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendPanel.html
Log:
svn merge -r1306:HEAD http://svn.geoext.org/core/trunk/geoext .
Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/data/FeatureReader.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/data/FeatureReader.js 2009-08-11 14:41:09 UTC (rev 1325)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/data/FeatureReader.js 2009-08-11 14:51:54 UTC (rev 1326)
@@ -109,7 +109,9 @@
values.state = feature.state;
values.fid = feature.fid;
- records[records.length] = new recordType(values, feature.id);
+ // newly inserted features need to be made into phantom records
+ var id = (feature.state === OpenLayers.State.INSERT) ? undefined : feature.id;
+ records[records.length] = new recordType(values, id);
}
}
Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/data/FeatureStore.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/data/FeatureStore.js 2009-08-11 14:41:09 UTC (rev 1325)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/data/FeatureStore.js 2009-08-11 14:51:54 UTC (rev 1326)
@@ -191,6 +191,27 @@
}
},
+ /** api: method[getRecordFromFeature]
+ * :arg feature: ``OpenLayers.Vector.Feature``
+ * :returns: :class:`GeoExt.data.FeatureRecord` The record corresponding
+ * to the given feature. Returns null if no record matches.
+ *
+ * Get the record corresponding to a feature.
+ */
+ getRecordFromFeature: function(feature) {
+ var record = null;
+ if(feature.state !== OpenLayers.State.INSERT) {
+ record = this.getById(feature.id);
+ } else {
+ var index = this.findBy(function(r) {
+ return r.get("feature") === feature;
+ });
+ if(index > -1) {
+ record = this.getAt(index);
+ }
+ }
+ return record;
+ },
/** private: method[onFeaturesAdded]
* Handler for layer featuresadded event
@@ -225,7 +246,7 @@
var features = evt.features, feature, record, i;
for(i=features.length - 1; i>=0; i--) {
feature = features[i];
- record = this.getById(feature.id);
+ record = this.getRecordFromFeature(feature);
if(record !== undefined) {
this._removing = true;
this.remove(record);
@@ -234,14 +255,14 @@
}
}
},
-
+
/** private: method[onFeatureModified]
* Handler for layer featuremodified event
*/
onFeatureModified: function(evt) {
if(!this._updating) {
var feature = evt.feature;
- var record = this.getById(feature.id);
+ var record = this.getRecordFromFeature(feature);
if(record !== undefined) {
record.beginEdit();
attributes = feature.attributes;
@@ -249,10 +270,10 @@
var fields = this.recordType.prototype.fields;
for(var i=0, len=fields.length; i<len; i++) {
var field = fields.items[i];
- var v = attributes[field.mapping || field.name] ||
- field.defaultValue;
- v = field.convert(v);
- record.set(field.name, v);
+ var key = field.mapping || field.name;
+ if(key in attributes) {
+ record.set(field.name, field.convert(attributes[key]));
+ }
}
}
// the calls to set below won't trigger "update"
Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendPanel.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendPanel.js 2009-08-11 14:41:09 UTC (rev 1325)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendPanel.js 2009-08-11 14:51:54 UTC (rev 1326)
@@ -1,299 +1,299 @@
-/**
- * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
- *
- * Published under the BSD license.
- * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
- * of the license.
- */
-
-/** api: (define)
- * module = GeoExt
- * class = LegendPanel
- * base_link = `Ext.Panel <http://extjs.com/deploy/dev/docs/?class=Ext.Panel>`_
- */
-
-Ext.namespace('GeoExt');
-
-/** api: constructor
- * .. class:: LegendPanel(config)
- *
- * A panel showing legends of all layers in a layer store.
- * Depending on the layer type, a legend renderer will be chosen.
- */
-GeoExt.LegendPanel = Ext.extend(Ext.Panel, {
-
- /** api: config[dynamic]
- * ``Boolean``
- * If false the LegendPanel will not listen to the add, remove and change
- * events of the LayerStore. So it will load with the initial state of
- * the LayerStore and not change anymore.
- */
- dynamic: true,
-
- /** api: config[showTitle]
- * ``Boolean``
- * Whether or not to show the title of a layer. This can be a global
- * setting for the whole panel, or it can be overridden on the LayerStore
- * record using the hideInLegend property.
- */
- showTitle: true,
-
- /** api: config[labelCls]
- * ``String``
- * Optional css class to use for the layer title labels.
- */
- labelCls: null,
-
- /** api: config[bodyStyle]
- * ``String``
- * Optional style to apply to the body of the legend panels.
- */
- bodyStyle: '',
-
- /** api: config[layerStore]
- * ``GeoExt.data.LayerStore``
- * The layer store containing layers to be displayed in the legend
- * container. If not provided it will be taken from the MapPanel.
- */
- layerStore: null,
-
- /** api: config[legendOptions]
- * ``Object``
- * Config options for the legend generator, i.e. the panel that provides
- * the legend image.
- */
-
- /** private: method[initComponent]
- * Initializes the legend panel.
- */
- initComponent: function() {
- GeoExt.LegendPanel.superclass.initComponent.call(this);
- },
-
- /** private: method[onRender]
- * Private method called when the legend panel is being rendered.
- */
- onRender: function() {
- GeoExt.LegendPanel.superclass.onRender.apply(this, arguments);
- if(!this.layerStore) {
- this.layerStore = GeoExt.MapPanel.guess().layers;
- }
- this.layerStore.each(function(record) {
- this.addLegend(record);
- }, this);
- if (this.dynamic) {
- this.layerStore.on({
- "add": this.onStoreAdd,
- "remove": this.onStoreRemove,
- "update": this.onStoreUpdate,
- scope: this
- });
- }
- this.doLayout();
- },
-
- /** private: method[recordIndexToPanelIndex]
- * Private method to get the panel index for a layer represented by a
- * record.
- *
- * :param index ``Integer`` The index of the record in the store.
- *
- * :return: ``Integer`` The index of the sub panel in this panel.
- */
- recordIndexToPanelIndex: function(index) {
- var store = this.layerStore;
- var count = store.getCount();
- var panelIndex = -1;
- var legendCount = this.items ? this.items.length : 0;
- for(var i=count-1; i>=0; --i) {
- var layer = store.getAt(i).get("layer");
- var legendGenerator = GeoExt[
- "Legend" + layer.CLASS_NAME.split(".").pop()
- ];
- if(layer.displayInLayerSwitcher && legendGenerator &&
- (store.getAt(i).get("hideInLegend") !== true)) {
- ++panelIndex;
- if(index === i || panelIndex > legendCount-1) {
- break;
- }
- }
- }
- return panelIndex;
- },
-
- /** private: method[onStoreUpdate]
- * Update a layer within the legend panel. Gets called when the store
- * fires the update event. This usually means the visibility of the layer
- * has changed.
- *
- * :param store: ``Ext.data.Store`` The store in which the record was
- * changed.
- * :param record: ``Ext.data.Record`` The record object corresponding
- * to the updated layer.
- * :param operation: ``String`` The type of operation.
- */
- onStoreUpdate: function(store, record, operation) {
- var layer = record.get('layer');
- var legend = this.getComponent(layer.id);
- if ((this.showTitle && !record.get('hideTitle')) &&
- (legend && legend.items.get(0).text !== record.get('title'))) {
- // we need to update the title
- legend.items.get(0).setText(record.get('title'));
- }
- if (legend) {
- legend.setVisible(layer.getVisibility() &&
- layer.displayInLayerSwitcher && !record.get('hideInLegend'));
- if (record.get('legendURL')) {
- var items = legend.findByType('gx_legendimage');
- for (var i=0, len=items.length; i<len; i++) {
- items[i].setUrl(record.get('legendURL'));
- }
- }
- }
- },
-
- /** private: method[onStoreAdd]
- * Private method called when a layer is added to the store.
- *
- * :param store: ``Ext.data.Store`` The store to which the record(s) was
- * added.
- * :param record: ``Ext.data.Record`` The record object(s) corresponding
- * to the added layers.
- * :param index: ``Integer`` The index of the inserted record.
- */
- onStoreAdd: function(store, records, index) {
- var panelIndex = this.recordIndexToPanelIndex(index+records.length-1);
- for (var i=0, len=records.length; i<len; i++) {
- this.addLegend(records[i], panelIndex);
- }
- this.doLayout();
- },
-
- /** private: method[onStoreRemove]
- * Private method called when a layer is removed from the store.
- *
- * :param store: ``Ext.data.Store`` The store from which the record(s) was
- * removed.
- * :param record: ``Ext.data.Record`` The record object(s) corresponding
- * to the removed layers.
- * :param index: ``Integer`` The index of the removed record.
- */
- onStoreRemove: function(store, record, index) {
- this.removeLegend(record);
- },
-
- /** private: method[removeLegend]
- * Remove the legend of a layer.
- * :param record: ``Ext.data.Record`` The record object from the layer
- * store to remove.
- */
- removeLegend: function(record) {
- var legend = this.getComponent(record.get('layer').id);
- if (legend) {
- this.remove(legend, true);
- this.doLayout();
- }
- },
-
- /** private: method[createLegendSubpanel]
- * Create a legend sub panel for the layer.
- *
- * :param record: ``Ext.data.Record`` The record object from the layer
- * store.
- *
- * :return: ``Ext.Panel`` The created panel per layer
- */
- createLegendSubpanel: function(record) {
- var layer = record.get('layer');
- var mainPanel = this.createMainPanel(record);
- if (mainPanel !== null) {
- // the default legend can be overridden by specifying a
- // legendURL property
- var legend;
- if (record.get('legendURL')) {
- legend = new GeoExt.LegendImage({url: record.get('legendURL')});
- mainPanel.add(legend);
- } else {
- var legendGenerator = GeoExt[
- "Legend" + layer.CLASS_NAME.split(".").pop()
- ];
- if (legendGenerator) {
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ *
+ * Published under the BSD license.
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
+ * of the license.
+ */
+
+/** api: (define)
+ * module = GeoExt
+ * class = LegendPanel
+ * base_link = `Ext.Panel <http://extjs.com/deploy/dev/docs/?class=Ext.Panel>`_
+ */
+
+Ext.namespace('GeoExt');
+
+/** api: constructor
+ * .. class:: LegendPanel(config)
+ *
+ * A panel showing legends of all layers in a layer store.
+ * Depending on the layer type, a legend renderer will be chosen.
+ */
+GeoExt.LegendPanel = Ext.extend(Ext.Panel, {
+
+ /** api: config[dynamic]
+ * ``Boolean``
+ * If false the LegendPanel will not listen to the add, remove and change
+ * events of the LayerStore. So it will load with the initial state of
+ * the LayerStore and not change anymore.
+ */
+ dynamic: true,
+
+ /** api: config[showTitle]
+ * ``Boolean``
+ * Whether or not to show the title of a layer. This can be a global
+ * setting for the whole panel, or it can be overridden on the LayerStore
+ * record using the hideInLegend property.
+ */
+ showTitle: true,
+
+ /** api: config[labelCls]
+ * ``String``
+ * Optional css class to use for the layer title labels.
+ */
+ labelCls: null,
+
+ /** api: config[bodyStyle]
+ * ``String``
+ * Optional style to apply to the body of the legend panels.
+ */
+ bodyStyle: '',
+
+ /** api: config[layerStore]
+ * ``GeoExt.data.LayerStore``
+ * The layer store containing layers to be displayed in the legend
+ * container. If not provided it will be taken from the MapPanel.
+ */
+ layerStore: null,
+
+ /** api: config[legendOptions]
+ * ``Object``
+ * Config options for the legend generator, i.e. the panel that provides
+ * the legend image.
+ */
+
+ /** private: method[initComponent]
+ * Initializes the legend panel.
+ */
+ initComponent: function() {
+ GeoExt.LegendPanel.superclass.initComponent.call(this);
+ },
+
+ /** private: method[onRender]
+ * Private method called when the legend panel is being rendered.
+ */
+ onRender: function() {
+ GeoExt.LegendPanel.superclass.onRender.apply(this, arguments);
+ if(!this.layerStore) {
+ this.layerStore = GeoExt.MapPanel.guess().layers;
+ }
+ this.layerStore.each(function(record) {
+ this.addLegend(record);
+ }, this);
+ if (this.dynamic) {
+ this.layerStore.on({
+ "add": this.onStoreAdd,
+ "remove": this.onStoreRemove,
+ "update": this.onStoreUpdate,
+ scope: this
+ });
+ }
+ this.doLayout();
+ },
+
+ /** private: method[recordIndexToPanelIndex]
+ * Private method to get the panel index for a layer represented by a
+ * record.
+ *
+ * :param index ``Integer`` The index of the record in the store.
+ *
+ * :return: ``Integer`` The index of the sub panel in this panel.
+ */
+ recordIndexToPanelIndex: function(index) {
+ var store = this.layerStore;
+ var count = store.getCount();
+ var panelIndex = -1;
+ var legendCount = this.items ? this.items.length : 0;
+ for(var i=count-1; i>=0; --i) {
+ var layer = store.getAt(i).get("layer");
+ var legendGenerator = GeoExt[
+ "Legend" + layer.CLASS_NAME.split(".").pop()
+ ];
+ if(layer.displayInLayerSwitcher && legendGenerator &&
+ (store.getAt(i).get("hideInLegend") !== true)) {
+ ++panelIndex;
+ if(index === i || panelIndex > legendCount-1) {
+ break;
+ }
+ }
+ }
+ return panelIndex;
+ },
+
+ /** private: method[onStoreUpdate]
+ * Update a layer within the legend panel. Gets called when the store
+ * fires the update event. This usually means the visibility of the layer
+ * has changed.
+ *
+ * :param store: ``Ext.data.Store`` The store in which the record was
+ * changed.
+ * :param record: ``Ext.data.Record`` The record object corresponding
+ * to the updated layer.
+ * :param operation: ``String`` The type of operation.
+ */
+ onStoreUpdate: function(store, record, operation) {
+ var layer = record.get('layer');
+ var legend = this.getComponent(layer.id);
+ if ((this.showTitle && !record.get('hideTitle')) &&
+ (legend && legend.items.get(0).text !== record.get('title'))) {
+ // we need to update the title
+ legend.items.get(0).setText(record.get('title'));
+ }
+ if (legend) {
+ legend.setVisible(layer.getVisibility() &&
+ layer.displayInLayerSwitcher && !record.get('hideInLegend'));
+ if (record.get('legendURL')) {
+ var items = legend.findByType('gx_legendimage');
+ for (var i=0, len=items.length; i<len; i++) {
+ items[i].setUrl(record.get('legendURL'));
+ }
+ }
+ }
+ },
+
+ /** private: method[onStoreAdd]
+ * Private method called when a layer is added to the store.
+ *
+ * :param store: ``Ext.data.Store`` The store to which the record(s) was
+ * added.
+ * :param record: ``Ext.data.Record`` The record object(s) corresponding
+ * to the added layers.
+ * :param index: ``Integer`` The index of the inserted record.
+ */
+ onStoreAdd: function(store, records, index) {
+ var panelIndex = this.recordIndexToPanelIndex(index+records.length-1);
+ for (var i=0, len=records.length; i<len; i++) {
+ this.addLegend(records[i], panelIndex);
+ }
+ this.doLayout();
+ },
+
+ /** private: method[onStoreRemove]
+ * Private method called when a layer is removed from the store.
+ *
+ * :param store: ``Ext.data.Store`` The store from which the record(s) was
+ * removed.
+ * :param record: ``Ext.data.Record`` The record object(s) corresponding
+ * to the removed layers.
+ * :param index: ``Integer`` The index of the removed record.
+ */
+ onStoreRemove: function(store, record, index) {
+ this.removeLegend(record);
+ },
+
+ /** private: method[removeLegend]
+ * Remove the legend of a layer.
+ * :param record: ``Ext.data.Record`` The record object from the layer
+ * store to remove.
+ */
+ removeLegend: function(record) {
+ var legend = this.getComponent(record.get('layer').id);
+ if (legend) {
+ this.remove(legend, true);
+ this.doLayout();
+ }
+ },
+
+ /** private: method[createLegendSubpanel]
+ * Create a legend sub panel for the layer.
+ *
+ * :param record: ``Ext.data.Record`` The record object from the layer
+ * store.
+ *
+ * :return: ``Ext.Panel`` The created panel per layer
+ */
+ createLegendSubpanel: function(record) {
+ var layer = record.get('layer');
+ var mainPanel = this.createMainPanel(record);
+ if (mainPanel !== null) {
+ // the default legend can be overridden by specifying a
+ // legendURL property
+ var legend;
+ if (record.get('legendURL')) {
+ legend = new GeoExt.LegendImage({url: record.get('legendURL')});
+ mainPanel.add(legend);
+ } else {
+ var legendGenerator = GeoExt[
+ "Legend" + layer.CLASS_NAME.split(".").pop()
+ ];
+ if (legendGenerator) {
legend = new legendGenerator(Ext.applyIf({
layer: layer,
record: record
- }, this.legendOptions));
- mainPanel.add(legend);
- }
- }
- }
- return mainPanel;
- },
-
- /** private: method[addLegend]
- * Add a legend for the layer.
- *
- * :param record: ``Ext.data.Record`` The record object from the layer
- * store.
- * :param index: ``Integer`` The position at which to add the legend.
- */
- addLegend: function(record, index) {
- index = index || 0;
- var layer = record.get('layer');
- var legendSubpanel = this.createLegendSubpanel(record);
- if (legendSubpanel !== null) {
- legendSubpanel.setVisible(layer.getVisibility());
- this.insert(index, legendSubpanel);
- }
- },
-
- /** private: method[createMainPanel]
- * Creates the main panel with a title for the layer.
- *
- * :param record: ``Ext.data.Record`` The record object from the layer
- * store.
- *
- * :return: ``Ext.Panel`` The created main panel with a label.
- */
- createMainPanel: function(record) {
- var layer = record.get('layer');
- var panel = null;
- var legendGenerator = GeoExt[
- "Legend" + layer.CLASS_NAME.split(".").pop()
- ];
- if (layer.displayInLayerSwitcher && !record.get('hideInLegend') &&
- legendGenerator) {
- var panelConfig = {
- id: layer.id,
- border: false,
- bodyBorder: false,
- bodyStyle: this.bodyStyle,
- items: [
- new Ext.form.Label({
- text: (this.showTitle && !record.get('hideTitle')) ?
- layer.name : '',
- cls: 'x-form-item x-form-item-label' +
- (this.labelCls ? ' ' + this.labelCls : '')
- })
- ]
- };
- panel = new Ext.Panel(panelConfig);
- }
- return panel;
- },
-
- /** private: method[onDestroy]
- * Private method called during the destroy sequence.
- */
- onDestroy: function() {
- if(this.layerStore) {
- this.layerStore.un("add", this.onStoreAdd, this);
- this.layerStore.un("remove", this.onStoreRemove, this);
- this.layerStore.un("update", this.onStoreUpdate, this);
- }
- GeoExt.LegendPanel.superclass.onDestroy.apply(this, arguments);
- }
-
-});
-
-/** api: xtype = gx_legendpanel */
-Ext.reg('gx_legendpanel', GeoExt.LegendPanel);
+ }, this.legendOptions));
+ mainPanel.add(legend);
+ }
+ }
+ }
+ return mainPanel;
+ },
+
+ /** private: method[addLegend]
+ * Add a legend for the layer.
+ *
+ * :param record: ``Ext.data.Record`` The record object from the layer
+ * store.
+ * :param index: ``Integer`` The position at which to add the legend.
+ */
+ addLegend: function(record, index) {
+ index = index || 0;
+ var layer = record.get('layer');
+ var legendSubpanel = this.createLegendSubpanel(record);
+ if (legendSubpanel !== null) {
+ legendSubpanel.setVisible(layer.getVisibility());
+ this.insert(index, legendSubpanel);
+ }
+ },
+
+ /** private: method[createMainPanel]
+ * Creates the main panel with a title for the layer.
+ *
+ * :param record: ``Ext.data.Record`` The record object from the layer
+ * store.
+ *
+ * :return: ``Ext.Panel`` The created main panel with a label.
+ */
+ createMainPanel: function(record) {
+ var layer = record.get('layer');
+ var panel = null;
+ var legendGenerator = GeoExt[
+ "Legend" + layer.CLASS_NAME.split(".").pop()
+ ];
+ if (layer.displayInLayerSwitcher && !record.get('hideInLegend') &&
+ legendGenerator) {
+ var panelConfig = {
+ id: layer.id,
+ border: false,
+ bodyBorder: false,
+ bodyStyle: this.bodyStyle,
+ items: [
+ new Ext.form.Label({
+ text: (this.showTitle && !record.get('hideTitle')) ?
+ layer.name : '',
+ cls: 'x-form-item x-form-item-label' +
+ (this.labelCls ? ' ' + this.labelCls : '')
+ })
+ ]
+ };
+ panel = new Ext.Panel(panelConfig);
+ }
+ return panel;
+ },
+
+ /** private: method[onDestroy]
+ * Private method called during the destroy sequence.
+ */
+ onDestroy: function() {
+ if(this.layerStore) {
+ this.layerStore.un("add", this.onStoreAdd, this);
+ this.layerStore.un("remove", this.onStoreRemove, this);
+ this.layerStore.un("update", this.onStoreUpdate, this);
+ }
+ GeoExt.LegendPanel.superclass.onDestroy.apply(this, arguments);
+ }
+
+});
+
+/** api: xtype = gx_legendpanel */
+Ext.reg('gx_legendpanel', GeoExt.LegendPanel);
Modified: sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendWMS.js
===================================================================
--- sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendWMS.js 2009-08-11 14:41:09 UTC (rev 1325)
+++ sandbox/camptocamp/geobretagne/lib/GeoExt/widgets/LegendWMS.js 2009-08-11 14:51:54 UTC (rev 1326)
@@ -1,127 +1,127 @@
-/**
- * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
- *
- * Published under the BSD license.
- * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
- * of the license.
- */
-
-/**
- * @include GeoExt/widgets/LegendImage.js
- */
-
-/** api: (define)
- * module = GeoExt
- * class = LegendWMS
- * base_link = `Ext.Panel <http://extjs.com/deploy/dev/docs/?class=Ext.Panel>`_
- */
-Ext.namespace('GeoExt');
-
-/** api: constructor
- * .. class:: LegendWMS(config)
- *
- * Show a legend image for a WMS layer.
- */
-GeoExt.LegendWMS = Ext.extend(Ext.Panel, {
-
- /** api: config[imageFormat]
- * ``String``
- * The image format to request the legend image in if the url cannot be
- * determined from the styles field of the layer record. Defaults to
- * image/gif.
- */
- imageFormat: "image/gif",
-
- /** api: config[defaultStyleIsFirst]
- * ``String``
- * The WMS spec does not say if the first style advertised for a layer in
- * a Capabilities document is the default style that the layer is
- * rendered with. We make this assumption by default. To be strictly WMS
- * compliant, set this to false, but make sure to configure a STYLES
- * param with your WMS layers, otherwise LegendURLs advertised in the
- * GetCapabilities document cannot be used.
- */
- defaultStyleIsFirst: true,
-
- /** api: config[layer]
- * ``OpenLayers.Layer.WMS``
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ *
+ * Published under the BSD license.
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
+ * of the license.
+ */
+
+/**
+ * @include GeoExt/widgets/LegendImage.js
+ */
+
+/** api: (define)
+ * module = GeoExt
+ * class = LegendWMS
+ * base_link = `Ext.Panel <http://extjs.com/deploy/dev/docs/?class=Ext.Panel>`_
+ */
+Ext.namespace('GeoExt');
+
+/** api: constructor
+ * .. class:: LegendWMS(config)
+ *
+ * Show a legend image for a WMS layer.
+ */
+GeoExt.LegendWMS = Ext.extend(Ext.Panel, {
+
+ /** api: config[imageFormat]
+ * ``String``
+ * The image format to request the legend image in if the url cannot be
+ * determined from the styles field of the layer record. Defaults to
+ * image/gif.
+ */
+ imageFormat: "image/gif",
+
+ /** api: config[defaultStyleIsFirst]
+ * ``String``
+ * The WMS spec does not say if the first style advertised for a layer in
+ * a Capabilities document is the default style that the layer is
+ * rendered with. We make this assumption by default. To be strictly WMS
+ * compliant, set this to false, but make sure to configure a STYLES
+ * param with your WMS layers, otherwise LegendURLs advertised in the
+ * GetCapabilities document cannot be used.
+ */
+ defaultStyleIsFirst: true,
+
+ /** api: config[layer]
+ * ``OpenLayers.Layer.WMS``
* The WMS layer to request the legend for. Not required if record is
- * provided.
- */
+ * provided.
+ */
layer: null,
/** api: config[record]
* ``Ext.data.Record``
* optional record containing the layer
*/
- record: null,
-
- /** api: config[bodyBorder]
- * ``Boolean``
- * Show a border around the legend image or not. Default is false.
- */
- bodyBorder: false,
-
- /** private: method[initComponent]
- * Initializes the WMS legend. For group layers it will create multiple
- * image box components.
- */
- initComponent: function() {
+ record: null,
+
+ /** api: config[bodyBorder]
+ * ``Boolean``
+ * Show a border around the legend image or not. Default is false.
+ */
+ bodyBorder: false,
+
+ /** private: method[initComponent]
+ * Initializes the WMS legend. For group layers it will create multiple
+ * image box components.
+ */
+ initComponent: function() {
GeoExt.LegendWMS.superclass.initComponent.call(this);
if(!this.layer) {
this.layer = this.record.get("layer");
- }
- this.createLegend();
- },
-
- /** private: method[getLegendUrl]
- * :param layer: ``OpenLayers.Layer.WMS`` The OpenLayers WMS layer object
- * :param layerName: ``String`` The name of the layer
- * (used in the LAYERS parameter)
- * :return: ``String`` The url of the SLD WMS GetLegendGraphic request.
- *
- * Get the url for the SLD WMS GetLegendGraphic request.
- */
- getLegendUrl: function(layerName) {
- return this.layer.getFullRequestString({
- REQUEST: "GetLegendGraphic",
- WIDTH: null,
- HEIGHT: null,
- EXCEPTIONS: "application/vnd.ogc.se_xml",
- LAYER: layerName,
- LAYERS: null,
- SRS: null,
- FORMAT: this.imageFormat
- });
- },
-
- /** private: method[createLegend]
- * Add one BoxComponent per sublayer to this panel.
- */
- createLegend: function() {
+ }
+ this.createLegend();
+ },
+
+ /** private: method[getLegendUrl]
+ * :param layer: ``OpenLayers.Layer.WMS`` The OpenLayers WMS layer object
+ * :param layerName: ``String`` The name of the layer
+ * (used in the LAYERS parameter)
+ * :return: ``String`` The url of the SLD WMS GetLegendGraphic request.
+ *
+ * Get the url for the SLD WMS GetLegendGraphic request.
+ */
+ getLegendUrl: function(layerName) {
+ return this.layer.getFullRequestString({
+ REQUEST: "GetLegendGraphic",
+ WIDTH: null,
+ HEIGHT: null,
+ EXCEPTIONS: "application/vnd.ogc.se_xml",
+ LAYER: layerName,
+ LAYERS: null,
+ SRS: null,
+ FORMAT: this.imageFormat
+ });
+ },
+
+ /** private: method[createLegend]
+ * Add one BoxComponent per sublayer to this panel.
+ */
+ createLegend: function() {
var layers = (this.layer.params.LAYERS instanceof Array) ?
this.layer.params.LAYERS : this.layer.params.LAYERS.split(",");
var styleNames = this.layer.params.STYLES &&
this.layer.params.STYLES.split(",");
var styles = this.record && this.record.get("styles");
- var url, layerName, styleName;
- for (var i = 0, len = layers.length; i < len; i++){
- layerName = layers[i];
- if(styles) {
- styleName = styleNames && styleNames[i];
- if(styleName) {
- Ext.each(styles, function(s) {
- url = (s.name == styleName && s.legend) && s.legend.href;
- return !url;
- })
- } else if(this.defaultStyleIsFirst === true){
- url = styles[0].legend && styles[0].legend.href;
- }
+ var url, layerName, styleName;
+ for (var i = 0, len = layers.length; i < len; i++){
+ layerName = layers[i];
+ if(styles && styles.length > 0) {
+ styleName = styleNames && styleNames[i];
+ if(styleName) {
+ Ext.each(styles, function(s) {
+ url = (s.name == styleName && s.legend) && s.legend.href;
+ return !url;
+ })
+ } else if(this.defaultStyleIsFirst === true){
+ url = styles[0].legend && styles[0].legend.href;
+ }
}
- var legend = new GeoExt.LegendImage({url:
- url || this.getLegendUrl(layerName)});
- this.add(legend);
- }
- }
-
+ var legend = new GeoExt.LegendImage({url:
+ url || this.getLegendUrl(layerName)});
+ this.add(legend);
+ }
+ }
+
});
Modified: sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/FeatureStore.html
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/FeatureStore.html 2009-08-11 14:41:09 UTC (rev 1325)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/data/FeatureStore.html 2009-08-11 14:51:54 UTC (rev 1326)
@@ -156,6 +156,35 @@
'Adding a record with "add" does not add feature to layer if addRecordFilter returns false');
}
+ function test_getRecordFromFeature(t) {
+ t.plan(2);
+
+ var layer = new OpenLayers.Layer.Vector();
+ var store = new GeoExt.data.FeatureStore({
+ layer: layer
+ });
+ var features = [
+ new OpenLayers.Feature.Vector(),
+ new OpenLayers.Feature.Vector()
+ ];
+ features[0].state = OpenLayers.State.INSERT;
+ layer.addFeatures(features);
+
+ var record;
+
+ // confirm that we can get a phantom record
+ record = store.getRecordFromFeature(features[0]);
+ t.ok((record && record.get("feature")) === features[0],
+ "phantom record retrieved");
+
+ // confirm that we can get a normal record
+ record = store.getRecordFromFeature(features[1]);
+ t.ok((record && record.get("feature")) === features[1],
+ "normal record retrieved");
+
+ layer.destroy();
+ }
+
function test_addFeatures_removeFeatures(t) {
t.plan(5);
@@ -163,7 +192,11 @@
var features = [
new OpenLayers.Feature.Vector(),
new OpenLayers.Feature.Vector()
- ];
+ ];
+
+ // set state of one feature to insert to test phantom record removal
+ features[0].state = OpenLayers.State.INSERT;
+
var layer = new OpenLayers.Layer.Vector("Foo layer");
var store = new GeoExt.data.FeatureStore({
layer: layer
@@ -187,7 +220,7 @@
}
function test_featuremodified_update(t) {
- t.plan(8);
+ t.plan(10);
/*
* Set up
@@ -198,6 +231,8 @@
foo: "foo",
bar: "bar"
});
+ // confirm that we can update phantom records
+ feature.state = OpenLayers.State.INSERT;
id = feature.id;
@@ -221,11 +256,12 @@
fields: recordType,
data: [feature]
});
+ record = store.getRecordFromFeature(feature);
- t.eq(store.getById(id).get("foo"), "foo",
+ t.eq(record.get("foo"), "foo",
"record gets correct initial value for property \"foo\"");
- t.eq(store.getById(id).get("bar"), "bar",
+ t.eq(record.get("bar"), "bar",
"record gets correct initial value for property \"bar\"");
/*
@@ -237,21 +273,20 @@
feature.attributes.bar = "bar2";
layer.events.triggerEvent("featuremodified", {feature: feature});
- t.eq(store.getById(id).get("foo"), "foo2",
+ t.eq(record.get("foo"), "foo2",
"featuremodified event causes update of record property \"foo\"");
- t.eq(store.getById(id).get("bar"), "bar2",
+ t.eq(record.get("bar"), "bar2",
"featuremodified event causes update of record property \"bar\"");
// update
- record = store.getById(id);
record.set("foo", "foo3");
record.set("bar", "bar3");
- t.eq(layer.getFeatureById(id).attributes.foo, "foo3",
+ t.eq(feature.attributes.foo, "foo3",
"update event causes update of feature property \"foo\"");
- t.eq(layer.getFeatureById(id).attributes.bar, "bar3",
+ t.eq(feature.attributes.bar, "bar3",
"update event causes update of feature property \"bar\"");
// make sure calling record.set didn't add any attributes
@@ -266,8 +301,17 @@
store.getById(feature2.id).set("bar", "bar_f2");
t.eq(feature2.attributes.bar, "bar_f2", "previously undefined attribute set correctly");
+
- }
+ // update with falsey vlues
+ feature.attributes.foo = false;
+ feature.attributes.bar = 0;
+ layer.events.triggerEvent("featuremodified", {feature: feature});
+
+ t.eq(record.get("foo"), false, "false correctly set");
+ t.eq(record.get("bar"), 0, "0 correctly set");
+
+ }
</script>
<body>
Modified: sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendPanel.html
===================================================================
--- sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendPanel.html 2009-08-11 14:41:09 UTC (rev 1325)
+++ sandbox/camptocamp/geobretagne/tests/lib/GeoExt/widgets/LegendPanel.html 2009-08-11 14:51:54 UTC (rev 1326)
@@ -1,196 +1,196 @@
-<!DOCTYPE html>
-<html debug="true">
- <head>
- <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
- <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
- <script type="text/javascript" src="../../../../../ext/ext-all.js"></script>
- <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
-
- <script type="text/javascript">
-
- function loadMapPanel() {
- mapPanel = new GeoExt.MapPanel({
- // panel options
- id: "map-panel",
- title: "GeoExt MapPanel",
- renderTo: "mappanel",
- height: 400,
- width: 600,
- // map panel-specific options
- layers: [
- new OpenLayers.Layer.WMS("test", '/ows', {layers: 'a'})
- ],
- center: new OpenLayers.LonLat(5, 45),
- zoom: 4
- });
-
- return mapPanel;
- }
-
- function test_legendurl(t) {
- t.plan(3);
- var mapPanel = loadMapPanel();
- var lp = new GeoExt.LegendPanel({
- renderTo: 'legendpanel'});
- lp.render();
-
- var newUrl = "http://trac.geoext.org/chrome/site/img/GeoExt.png";
- mapPanel.layers.getAt(0).set("legendURL", newUrl);
-
- var item = lp.getComponent(mapPanel.map.layers[0].id);
- var url = item.items.get(1).items.get(0).getEl().dom.src;
- t.eq(url, newUrl, "Update the image with the provided legendURL");
-
- var vectorLayer = new OpenLayers.Layer.Vector("vector layer");
- mapPanel.map.addLayer(vectorLayer);
-
- vectorLayer.setVisibility(false);
-
- t.eq(lp.items.length, 1, "Currently there are no legends for non WMS layers");
-
- var wms = new OpenLayers.Layer.WMS("testArray", '/ows', {layers: ['a', 'b', 'c']});
- mapPanel.map.addLayer(wms);
-
- t.eq(lp.items.length, 2, "The legend panel can deal with WMS layers which have a LAYERS params which is an array");
-
- lp.destroy();
- mapPanel.destroy();
- }
-
- function test_togglevisibility(t) {
- t.plan(2);
- var mapPanel = loadMapPanel();
- var lp = new GeoExt.LegendPanel({
- renderTo: 'legendpanel'});
- lp.render();
-
- mapPanel.map.layers[0].setVisibility(false);
- var id = mapPanel.layers.getAt(0).get('layer').id;
- t.eq(lp.getComponent(id).hidden, true, "Layer has been hidden in legend");
-
- mapPanel.map.layers[0].setVisibility(true);
- t.eq(lp.getComponent(id).hidden, false, "Layer has been made visible again in legend");
-
- lp.destroy();
- mapPanel.destroy();
- }
-
- function test_hide(t) {
- t.plan(1);
- var mapPanel = loadMapPanel();
- var lp = new GeoExt.LegendPanel({
- renderTo: 'legendpanel'});
- lp.render();
-
- mapPanel.layers.getAt(0).set("hideInLegend", true);
- var id = mapPanel.layers.getAt(0).get('layer').id;
- t.eq(lp.getComponent(id).hidden, true, "Layer has been hidden in legend");
-
- lp.destroy();
- mapPanel.destroy();
- }
-
- function test_dynamic(t) {
- t.plan(1);
- var mapPanel = loadMapPanel();
- var lp = new GeoExt.LegendPanel({
- dynamic: false,
- renderTo: 'legendpanel'});
- lp.render();
-
- var layer;
- layer = new OpenLayers.Layer.WMS("test2", '/ows', {layers: 'b', format: 'image/png', transparent: 'TRUE'});
- mapPanel.map.addLayer(layer);
-
- t.eq(lp.items.length, 1, "If dynamic is false, do not add or remove layers from legend");
-
- lp.destroy();
- mapPanel.destroy();
- }
-
- function test_wms(t) {
- t.plan(3);
- var mapPanel = loadMapPanel();
- var LegendWMS = GeoExt.LegendWMS;
- GeoExt.LegendWMS = function(config) {
- t.ok(config.record == mapPanel.layers.getAt(0), "layer record passed correctly");
- t.ok(config.layer == mapPanel.map.layers[0], "layer passed correctly");
- t.eq(config.foo, "bar", "legendOptions passed correctly");
- return new Ext.Panel();
- }
- var lp = new GeoExt.LegendPanel({
- renderTo: 'legendpanel',
- legendOptions: {foo: "bar"}
- });
- lp.render();
-
- lp.destroy();
- mapPanel.destroy();
- GeoExt.LegendWMS = LegendWMS;
- }
-
- function test_addremove(t) {
- t.plan(4);
- var mapPanel = loadMapPanel();
- var lp = new GeoExt.LegendPanel({
- renderTo: 'legendpanel'});
- lp.render();
- t.eq(lp.items.length, 1, "Same number of layers in legend panel and in map");
-
- var item = lp.getComponent(mapPanel.map.layers[0].id);
-
- var layer;
- layer = new OpenLayers.Layer.WMS("test2", '/ows', {layers: 'b', format: 'image/png', transparent: 'TRUE'});
- mapPanel.map.addLayer(layer);
-
- t.eq(lp.items.length, 2, "New WMS layer has been added");
-
- layer = new OpenLayers.Layer.WMS("test3", '/ows', {layers: 'c'}, {visibility: false});
- mapPanel.map.addLayer(layer);
-
- t.eq(lp.items.length, 3, "A non visible WMS layer will be added but will be invisible");
-
- mapPanel.map.removeLayer(mapPanel.map.layers[0]);
- t.eq(lp.items.length, 2, "Removing the WMS layer really removes the legend from the panel");
-
- lp.destroy();
- mapPanel.destroy();
- }
-
- function test_changelayername(t) {
- t.plan(3);
- var mapPanel = loadMapPanel();
- var lp = new GeoExt.LegendPanel({
- renderTo: 'legendpanel'});
- lp.render();
-
- var layer = mapPanel.map.layers[0];
- var cmp = lp.getComponent(layer.id);
- t.eq(cmp.items.get(0).text, 'test', "Layer name is test before change");
-
- layer.setName("My new name");
-
- t.eq(cmp.items.get(0).text, "My new name", "Layer name was changed correctly to 'My new name'");
-
- lp.destroy();
-
- var lp = new GeoExt.LegendPanel({
- showTitle: false,
- renderTo: 'legendpanel'});
- lp.render();
-
- layer.setName("My new new name");
- var cmp = lp.getComponent(layer.id);
- t.eq(cmp.items.get(0).text, "", "When showTitle is false, there is no label for a layer and it is not changed");
-
- lp.destroy();
-
- mapPanel.destroy();
- }
-
- </script>
- <body>
- <div id="legendpanel"></div>
- <div id="mappanel"></div>
- </body>
-</html>
+<!DOCTYPE html>
+<html debug="true">
+ <head>
+ <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
+ <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
+ <script type="text/javascript" src="../../../../../ext/ext-all.js"></script>
+ <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
+
+ <script type="text/javascript">
+
+ function loadMapPanel() {
+ mapPanel = new GeoExt.MapPanel({
+ // panel options
+ id: "map-panel",
+ title: "GeoExt MapPanel",
+ renderTo: "mappanel",
+ height: 400,
+ width: 600,
+ // map panel-specific options
+ layers: [
+ new OpenLayers.Layer.WMS("test", '/ows', {layers: 'a'})
+ ],
+ center: new OpenLayers.LonLat(5, 45),
+ zoom: 4
+ });
+
+ return mapPanel;
+ }
+
+ function test_legendurl(t) {
+ t.plan(3);
+ var mapPanel = loadMapPanel();
+ var lp = new GeoExt.LegendPanel({
+ renderTo: 'legendpanel'});
+ lp.render();
+
+ var newUrl = "http://trac.geoext.org/chrome/site/img/GeoExt.png";
+ mapPanel.layers.getAt(0).set("legendURL", newUrl);
+
+ var item = lp.getComponent(mapPanel.map.layers[0].id);
+ var url = item.items.get(1).items.get(0).getEl().dom.src;
+ t.eq(url, newUrl, "Update the image with the provided legendURL");
+
+ var vectorLayer = new OpenLayers.Layer.Vector("vector layer");
+ mapPanel.map.addLayer(vectorLayer);
+
+ vectorLayer.setVisibility(false);
+
+ t.eq(lp.items.length, 1, "Currently there are no legends for non WMS layers");
+
+ var wms = new OpenLayers.Layer.WMS("testArray", '/ows', {layers: ['a', 'b', 'c']});
+ mapPanel.map.addLayer(wms);
+
+ t.eq(lp.items.length, 2, "The legend panel can deal with WMS layers which have a LAYERS params which is an array");
+
+ lp.destroy();
+ mapPanel.destroy();
+ }
+
+ function test_togglevisibility(t) {
+ t.plan(2);
+ var mapPanel = loadMapPanel();
+ var lp = new GeoExt.LegendPanel({
+ renderTo: 'legendpanel'});
+ lp.render();
+
+ mapPanel.map.layers[0].setVisibility(false);
+ var id = mapPanel.layers.getAt(0).get('layer').id;
+ t.eq(lp.getComponent(id).hidden, true, "Layer has been hidden in legend");
+
+ mapPanel.map.layers[0].setVisibility(true);
+ t.eq(lp.getComponent(id).hidden, false, "Layer has been made visible again in legend");
+
+ lp.destroy();
+ mapPanel.destroy();
+ }
+
+ function test_hide(t) {
+ t.plan(1);
+ var mapPanel = loadMapPanel();
+ var lp = new GeoExt.LegendPanel({
+ renderTo: 'legendpanel'});
+ lp.render();
+
+ mapPanel.layers.getAt(0).set("hideInLegend", true);
+ var id = mapPanel.layers.getAt(0).get('layer').id;
+ t.eq(lp.getComponent(id).hidden, true, "Layer has been hidden in legend");
+
+ lp.destroy();
+ mapPanel.destroy();
+ }
+
+ function test_dynamic(t) {
+ t.plan(1);
+ var mapPanel = loadMapPanel();
+ var lp = new GeoExt.LegendPanel({
+ dynamic: false,
+ renderTo: 'legendpanel'});
+ lp.render();
+
+ var layer;
+ layer = new OpenLayers.Layer.WMS("test2", '/ows', {layers: 'b', format: 'image/png', transparent: 'TRUE'});
+ mapPanel.map.addLayer(layer);
+
+ t.eq(lp.items.length, 1, "If dynamic is false, do not add or remove layers from legend");
+
+ lp.destroy();
+ mapPanel.destroy();
+ }
+
+ function test_wms(t) {
+ t.plan(3);
+ var mapPanel = loadMapPanel();
+ var LegendWMS = GeoExt.LegendWMS;
+ GeoExt.LegendWMS = function(config) {
+ t.ok(config.record == mapPanel.layers.getAt(0), "layer record passed correctly");
+ t.ok(config.layer == mapPanel.map.layers[0], "layer passed correctly");
+ t.eq(config.foo, "bar", "legendOptions passed correctly");
+ return new Ext.Panel();
+ }
+ var lp = new GeoExt.LegendPanel({
+ renderTo: 'legendpanel',
+ legendOptions: {foo: "bar"}
+ });
+ lp.render();
+
+ lp.destroy();
+ mapPanel.destroy();
+ GeoExt.LegendWMS = LegendWMS;
+ }
+
+ function test_addremove(t) {
+ t.plan(4);
+ var mapPanel = loadMapPanel();
+ var lp = new GeoExt.LegendPanel({
+ renderTo: 'legendpanel'});
+ lp.render();
+ t.eq(lp.items.length, 1, "Same number of layers in legend panel and in map");
+
+ var item = lp.getComponent(mapPanel.map.layers[0].id);
+
+ var layer;
+ layer = new OpenLayers.Layer.WMS("test2", '/ows', {layers: 'b', format: 'image/png', transparent: 'TRUE'});
+ mapPanel.map.addLayer(layer);
+
+ t.eq(lp.items.length, 2, "New WMS layer has been added");
+
+ layer = new OpenLayers.Layer.WMS("test3", '/ows', {layers: 'c'}, {visibility: false});
+ mapPanel.map.addLayer(layer);
+
+ t.eq(lp.items.length, 3, "A non visible WMS layer will be added but will be invisible");
+
+ mapPanel.map.removeLayer(mapPanel.map.layers[0]);
+ t.eq(lp.items.length, 2, "Removing the WMS layer really removes the legend from the panel");
+
+ lp.destroy();
+ mapPanel.destroy();
+ }
+
+ function test_changelayername(t) {
+ t.plan(3);
+ var mapPanel = loadMapPanel();
+ var lp = new GeoExt.LegendPanel({
+ renderTo: 'legendpanel'});
+ lp.render();
+
+ var layer = mapPanel.map.layers[0];
+ var cmp = lp.getComponent(layer.id);
+ t.eq(cmp.items.get(0).text, 'test', "Layer name is test before change");
+
+ layer.setName("My new name");
+
+ t.eq(cmp.items.get(0).text, "My new name", "Layer name was changed correctly to 'My new name'");
+
+ lp.destroy();
+
+ var lp = new GeoExt.LegendPanel({
+ showTitle: false,
+ renderTo: 'legendpanel'});
+ lp.render();
+
+ layer.setName("My new new name");
+ var cmp = lp.getComponent(layer.id);
+ t.eq(cmp.items.get(0).text, "", "When showTitle is false, there is no label for a layer and it is not changed");
+
+ lp.destroy();
+
+ mapPanel.destroy();
+ }
+
+ </script>
+ <body>
+ <div id="legendpanel"></div>
+ <div id="mappanel"></div>
+ </body>
+</html>
More information about the Commits
mailing list