| 45 | | * Property: layerConfig |
|---|
| 46 | | * {Object} Hash of layers with config parameters |
|---|
| 47 | | * |
|---|
| 48 | | * Should look like : |
|---|
| 49 | | * |
|---|
| 50 | | { |
|---|
| 51 | | campfacilities: { |
|---|
| 52 | | text: 'Camps', |
|---|
| 53 | | strategy: new OpenLayers.Strategy.BBOX({ratio: 4}), |
|---|
| 54 | | protocol: new mapfish.Protocol.MapFish({'url': 'camps'}), |
|---|
| 55 | | format: new OpenLayers.Format.GeoJSON(), |
|---|
| 56 | | featuretypes: { |
|---|
| 57 | | geometry: { |
|---|
| 58 | | type: OpenLayers.Geometry.MultiPolygon |
|---|
| 59 | | }, |
|---|
| 60 | | // See the documentation in the mapfish.widgets.editing.*Property classes for |
|---|
| 61 | | // more details |
|---|
| 62 | | properties: [ |
|---|
| 63 | | new mapfish.widgets.editing.StringProperty({name: 'comment'}), |
|---|
| 64 | | new mapfish.widgets.editing.IntegerProperty({name: 'status'}), |
|---|
| 65 | | new mapfish.widgets.editing.ComboProperty({name: '_type', url: 'campfacilitytypes'}), |
|---|
| 66 | | new mapfish.widgets.editing.IntegerProperty({name: 'name', showInGrid: true}), |
|---|
| 67 | | new mapfish.widgets.editing.FloatProperty({name: 'camp_id'}) |
|---|
| 68 | | ] |
|---|
| 69 | | |
|---|
| 70 | | } |
|---|
| 71 | | }, |
|---|
| 72 | | refugees : { |
|---|
| 73 | | ... |
|---|
| 74 | | } |
|---|
| 75 | | } |
|---|
| | 57 | * APIProperty: layerConfig |
|---|
| | 58 | * {Object} Hash of layers with config parameters. |
|---|
| | 59 | * |
|---|
| | 60 | * Example: |
|---|
| | 61 | * (code start) |
|---|
| | 62 | * { |
|---|
| | 63 | * campfacilities: { |
|---|
| | 64 | * text: "Camps", |
|---|
| | 65 | * protocol: new mapfish.Protocol.MapFish({url: "camps"}), |
|---|
| | 66 | * featuretypes: { |
|---|
| | 67 | * geometry: { |
|---|
| | 68 | * type: OpenLayers.Geometry.MultiPolygon |
|---|
| | 69 | * }, |
|---|
| | 70 | * // See the documentation in the mapfish.widgets.editing.*Property |
|---|
| | 71 | * // classes for more details |
|---|
| | 72 | * properties: [ |
|---|
| | 73 | * new mapfish.widgets.editing.StringProperty( |
|---|
| | 74 | * {name: 'comment'}), |
|---|
| | 75 | * new mapfish.widgets.editing.IntegerProperty( |
|---|
| | 76 | * {name: 'status'}), |
|---|
| | 77 | * new mapfish.widgets.editing.ComboProperty( |
|---|
| | 78 | * {name: '_type', url: 'campfacilitytypes'}), |
|---|
| | 79 | * new mapfish.widgets.editing.IntegerProperty( |
|---|
| | 80 | * {name: 'name', showInGrid: true}), |
|---|
| | 81 | * new mapfish.widgets.editing.FloatProperty( |
|---|
| | 82 | * {name: 'camp_id'}) |
|---|
| | 83 | * ] |
|---|
| | 84 | * } |
|---|
| | 85 | * }, |
|---|
| | 86 | * refugees: { |
|---|
| | 87 | * ... |
|---|
| | 88 | * } |
|---|
| | 89 | * } |
|---|
| | 90 | * (end) |
|---|
| 176 | | window.onbeforeunload = (function(e) { |
|---|
| 177 | | if (this.isDirty()) { |
|---|
| 178 | | return "There are unsaved changes!"; |
|---|
| 179 | | } |
|---|
| 180 | | }).createDelegate(this); |
|---|
| 181 | | |
|---|
| 182 | | this.addEvents( |
|---|
| 183 | | /** |
|---|
| 184 | | * @event beforecommit |
|---|
| 185 | | * Triggered when the commit button is hit and |
|---|
| 186 | | * before the actual commit occurs |
|---|
| 187 | | */ |
|---|
| 188 | | 'beforecommit', |
|---|
| 189 | | /** |
|---|
| 190 | | * @event commit |
|---|
| 191 | | * Triggered when the commit is done. |
|---|
| 192 | | */ |
|---|
| 193 | | 'commit' |
|---|
| 194 | | ); |
|---|
| 195 | | }, |
|---|
| 196 | | |
|---|
| 197 | | /** |
|---|
| 198 | | * Method: initToolbar |
|---|
| 199 | | * |
|---|
| 200 | | */ |
|---|
| 201 | | initToolbar: function() { |
|---|
| | 201 | this.add(this.createLayerCombo()); |
|---|
| | 202 | |
|---|
| | 203 | this.on("destroy", this.destroyResources, this); |
|---|
| | 204 | |
|---|
| | 205 | this.on("enable", this.setUp, this); |
|---|
| | 206 | this.on("disable", this.tearDown, this); |
|---|
| | 207 | |
|---|
| | 208 | // for accordion |
|---|
| | 209 | this.on('expand', this.setUp, this); |
|---|
| | 210 | this.on('collapse', this.tearDown, this); |
|---|
| | 211 | |
|---|
| | 212 | // for tabs |
|---|
| | 213 | this.on('activate', this.setUp, this); |
|---|
| | 214 | this.on('deactivate', this.tearDown, this); |
|---|
| | 215 | |
|---|
| | 216 | this.addEvents('beforecommit', 'commit'); |
|---|
| | 217 | }, |
|---|
| | 218 | |
|---|
| | 219 | /** |
|---|
| | 220 | * Method: createToolbar |
|---|
| | 221 | * Create the toolbar with the editing tools. |
|---|
| | 222 | * |
|---|
| | 223 | * Returns: |
|---|
| | 224 | * {<mapfish.widgets.toolbar.Toolbar>} MapFish toolbar. |
|---|
| | 225 | */ |
|---|
| | 226 | createToolbar: function() { |
|---|
| 242 | | this.tbar = tb; |
|---|
| 243 | | }, |
|---|
| 244 | | |
|---|
| 245 | | /** |
|---|
| 246 | | * Method: isDirty |
|---|
| 247 | | * Checks for unsaved (uncommited) changes |
|---|
| 248 | | * |
|---|
| 249 | | * Returns |
|---|
| 250 | | * {Boolean} - true is there are no unsaved changes |
|---|
| 251 | | */ |
|---|
| 252 | | isDirty: function() { |
|---|
| 253 | | return (this.store && |
|---|
| 254 | | this.store.getCount() > 0); |
|---|
| 255 | | }, |
|---|
| 256 | | |
|---|
| 257 | | /** |
|---|
| 258 | | * Method: prepareChangeLayer |
|---|
| 259 | | * Is called when the user selects a layer in the combobox. |
|---|
| 260 | | * Makes the sanity checks before we change layer. |
|---|
| 261 | | * |
|---|
| 262 | | * Parameters: |
|---|
| 263 | | * layer - {String} The layer id (key in layerConfig) |
|---|
| 264 | | */ |
|---|
| 265 | | prepareChangeLayer: function(layer) { |
|---|
| | 267 | }, |
|---|
| | 268 | |
|---|
| | 269 | /** |
|---|
| | 270 | * Method: refreshFeatures |
|---|
| | 271 | * Refresh the vector layor. |
|---|
| | 272 | */ |
|---|
| | 273 | refreshFeatures: function() { |
|---|
| | 274 | // we created the layer ourself so we're assured there's |
|---|
| | 275 | // only one strategy configured into it |
|---|
| | 276 | this.layer.strategies[0].update({force: true}); |
|---|
| | 277 | }, |
|---|
| | 278 | |
|---|
| | 279 | /** |
|---|
| | 280 | * Method: commitFeatures |
|---|
| | 281 | * Commit the modified features. |
|---|
| | 282 | */ |
|---|
| | 283 | commitFeatures: function() { |
|---|
| | 284 | // callback func called on each update and create |
|---|
| | 285 | function onUpdateCreate(resp) { |
|---|
| | 286 | // if the modify feature control has a selected feature, |
|---|
| | 287 | // unselect it |
|---|
| | 288 | if (this.modifyFeatureControl.feature) { |
|---|
| | 289 | this.modifyFeatureControl.unselectFeature( |
|---|
| | 290 | {feature: this.modifyFeatureControl.feature} |
|---|
| | 291 | ); |
|---|
| | 292 | } |
|---|
| | 293 | var toDestroy = (resp.reqFeatures instanceof Array) ? |
|---|
| | 294 | resp.reqFeatures : [resp.reqFeatures]; |
|---|
| | 295 | this.layer.destroyFeatures(toDestroy); |
|---|
| | 296 | this.layer.addFeatures(resp.features); |
|---|
| | 297 | if (resp.last) { |
|---|
| | 298 | this.fireEvent("commit"); |
|---|
| | 299 | } |
|---|
| | 300 | } |
|---|
| | 301 | // callback func called on each delete |
|---|
| | 302 | function onDelete(resp) { |
|---|
| | 303 | var features = resp.reqFeatures; |
|---|
| | 304 | if (!(features instanceof Array)) { |
|---|
| | 305 | features = [features]; |
|---|
| | 306 | } |
|---|
| | 307 | this.layer.destroyFeatures(features); |
|---|
| | 308 | if (resp.last) { |
|---|
| | 309 | this.fireEvent("commit"); |
|---|
| | 310 | } |
|---|
| | 311 | } |
|---|
| | 312 | this.fireEvent("beforecommit"); |
|---|
| | 313 | this.layer.protocol.commit(this.layer.features, { |
|---|
| | 314 | "create": { |
|---|
| | 315 | scope: this, |
|---|
| | 316 | callback: onUpdateCreate |
|---|
| | 317 | }, |
|---|
| | 318 | "update": { |
|---|
| | 319 | scope: this, |
|---|
| | 320 | callback: onUpdateCreate |
|---|
| | 321 | }, |
|---|
| | 322 | "delete": { |
|---|
| | 323 | scope: this, |
|---|
| | 324 | callback: onDelete |
|---|
| | 325 | } |
|---|
| | 326 | }); |
|---|
| | 327 | }, |
|---|
| | 328 | |
|---|
| | 329 | /** |
|---|
| | 330 | * Method: deleteFeatures |
|---|
| | 331 | * |
|---|
| | 332 | * Returns: |
|---|
| | 333 | * {Array({<OpenLayers.Feature.Vector>})} The array of features |
|---|
| | 334 | * that are marked for deletion. |
|---|
| | 335 | */ |
|---|
| | 336 | deleteFeatures: function() { |
|---|
| | 337 | var toDelete = []; |
|---|
| | 338 | var selected = this.layer.selectedFeatures; |
|---|
| | 339 | for (var i = selected.length - 1; i >= 0; i--) { |
|---|
| | 340 | var feature = selected[i]; |
|---|
| | 341 | if (feature.state == OpenLayers.State.INSERT) { |
|---|
| | 342 | // feature was created as part of the current "transaction", |
|---|
| | 343 | // so just destroy it right away |
|---|
| | 344 | this.layer.destroyFeatures([feature]); |
|---|
| | 345 | } else { |
|---|
| | 346 | feature.state = OpenLayers.State.DELETE; |
|---|
| | 347 | toDelete.push(feature); |
|---|
| | 348 | } |
|---|
| | 349 | // if the modify feature control has a selected feature, |
|---|
| | 350 | // unselect it |
|---|
| | 351 | if (this.modifyFeatureControl.feature) { |
|---|
| | 352 | this.modifyFeatureControl.selectControl.unselect( |
|---|
| | 353 | this.modifyFeatureControl.feature |
|---|
| | 354 | ); |
|---|
| | 355 | } |
|---|
| | 356 | } |
|---|
| | 357 | return toDelete; |
|---|
| | 358 | }, |
|---|
| | 359 | |
|---|
| | 360 | /** |
|---|
| | 361 | * Method: createLayerCombo |
|---|
| | 362 | * Create a combobox to let user choose the layer to edit. |
|---|
| | 363 | * |
|---|
| | 364 | * Returns: |
|---|
| | 365 | * {Ext.form.ComboxBox} A combobox |
|---|
| | 366 | */ |
|---|
| | 367 | createLayerCombo: function() { |
|---|
| | 368 | var data = [[this.COMBO_NONE_VALUE, this.COMBO_NONE_NAME]]; |
|---|
| | 369 | for (var i in this.layerConfig) { |
|---|
| | 370 | data.push([i, this.layerConfig[i].text]); |
|---|
| | 371 | } |
|---|
| | 372 | var store = new Ext.data.SimpleStore({ |
|---|
| | 373 | fields: ['value', 'text'], |
|---|
| | 374 | data : data |
|---|
| | 375 | }); |
|---|
| | 376 | this.combo = new Ext.form.ComboBox({ |
|---|
| | 377 | fieldLabel: OpenLayers.i18n("mf.editing.comboLabel"), |
|---|
| | 378 | name: "editingLayer", |
|---|
| | 379 | hiddenName: "editingLayer", |
|---|
| | 380 | displayField: "text", |
|---|
| | 381 | valueField: "value", |
|---|
| | 382 | mode: "local", |
|---|
| | 383 | triggerAction: "all", |
|---|
| | 384 | editable: false, |
|---|
| | 385 | store: store, |
|---|
| | 386 | listeners: { |
|---|
| | 387 | select: function(combo, record, index) { |
|---|
| | 388 | this.prepareSwitchLayer(record.data.value); |
|---|
| | 389 | }, |
|---|
| | 390 | scope: this |
|---|
| | 391 | } |
|---|
| | 392 | }); |
|---|
| | 393 | return this.combo; |
|---|
| | 394 | }, |
|---|
| | 395 | |
|---|
| | 396 | /** |
|---|
| | 397 | * Method: prepareSwitchLayer |
|---|
| | 398 | * Called when the user selects a layer in the combobox. |
|---|
| | 399 | * |
|---|
| | 400 | * Parameters: |
|---|
| | 401 | * id - {String} The layer id (key in layerConfig) |
|---|
| | 402 | */ |
|---|
| | 403 | prepareSwitchLayer: function(id) { |
|---|
| 281 | | this.changeLayer(layer); |
|---|
| 282 | | } |
|---|
| 283 | | |
|---|
| 284 | | }, |
|---|
| 285 | | |
|---|
| 286 | | /** |
|---|
| 287 | | * Method: changeLayer |
|---|
| 288 | | * Is called by prepareChangeLayer |
|---|
| 289 | | * Builds the OL Layer, and Ext form and grid. |
|---|
| 290 | | * |
|---|
| 291 | | * Parameters: |
|---|
| 292 | | * layer - {String} The layer id (key in layerConfig) |
|---|
| 293 | | */ |
|---|
| 294 | | changeLayer: function(layer) { |
|---|
| 295 | | this.createLayer(layer); |
|---|
| 296 | | this.importBtn.enable(); |
|---|
| 297 | | this.buildAttributesForm(layer); |
|---|
| 298 | | this.buildFeatureGrid(layer); |
|---|
| | 418 | this.switchLayer(id); |
|---|
| | 419 | } |
|---|
| | 420 | }, |
|---|
| | 421 | |
|---|
| | 422 | /** |
|---|
| | 423 | * Method: switchLayer |
|---|
| | 424 | * |
|---|
| | 425 | * Parameters: |
|---|
| | 426 | * id - {String} The layer id (key in layerConfig) |
|---|
| | 427 | */ |
|---|
| | 428 | switchLayer: function(id) { |
|---|
| | 429 | if (id != this.COMBO_NONE_VALUE) { |
|---|
| | 430 | var config = this.layerConfig[id]; |
|---|
| | 431 | this.configureLayer(config); |
|---|
| | 432 | this.createStore(config); |
|---|
| | 433 | this.createModifyFeatureControl(); |
|---|
| | 434 | this.createDrawFeatureControl(config); |
|---|
| | 435 | this.createLayerStoreMediator(); |
|---|
| | 436 | this.importBtn.enable(); |
|---|
| | 437 | this.createForm(config); |
|---|
| | 438 | this.createGrid(config); |
|---|
| | 439 | } else { |
|---|
| | 440 | this.destroyAllResources(); |
|---|
| | 441 | } |
|---|
| | 442 | this.currentLayerId = id; |
|---|
| | 443 | }, |
|---|
| | 444 | |
|---|
| | 445 | /** |
|---|
| | 446 | * Method: configureLayer |
|---|
| | 447 | * |
|---|
| | 448 | * Parameters: |
|---|
| | 449 | * config - {Object} The layer configuration. |
|---|
| | 450 | */ |
|---|
| | 451 | configureLayer: function(config) { |
|---|
| | 452 | var layer = this.layer; |
|---|
| | 453 | if (!layer) { |
|---|
| | 454 | layer = this.layer = this.createLayer(); |
|---|
| | 455 | } |
|---|
| | 456 | // we don't want to destroy the protocol when the layer |
|---|
| | 457 | // is destroyed |
|---|
| | 458 | config.protocol.autoDestroy = false; |
|---|
| | 459 | layer.protocol = config.protocol; |
|---|
| | 460 | if (OpenLayers.Util.indexOf(this.map.layers, layer) < 0) { |
|---|
| | 461 | this.map.addLayer(layer); |
|---|
| | 462 | } |
|---|
| | 463 | layer.destroyFeatures(); |
|---|
| 303 | | * Creates the vector layer in the map, and the corresponding controls |
|---|
| 304 | | * for the map |
|---|
| 305 | | * |
|---|
| 306 | | * Parameters: |
|---|
| 307 | | * layer - {String} The layer id (key in layerConfig) |
|---|
| 308 | | */ |
|---|
| 309 | | // FIXME: this method does much more than creating a layer. It should be split. |
|---|
| 310 | | createLayer: function(layer) { |
|---|
| 311 | | var config = this.layerConfig[layer]; |
|---|
| 312 | | // sanity checks |
|---|
| 313 | | if (!config.text) { |
|---|
| 314 | | config.text = 'vector'; |
|---|
| 315 | | } |
|---|
| 316 | | |
|---|
| 317 | | this.getTopToolbar().deactivate(); |
|---|
| 318 | | if (this.modifyControl) { |
|---|
| 319 | | this.modifyControl.destroy(); |
|---|
| 320 | | this.getTopToolbar().getButtonForControl(this.modifyControl).destroy(); |
|---|
| 321 | | } |
|---|
| 322 | | if (this.drawFeatureControl) { |
|---|
| 323 | | this.drawFeatureControl.destroy(); |
|---|
| 324 | | this.getTopToolbar().getButtonForControl(this.drawFeatureControl).destroy(); |
|---|
| 325 | | } |
|---|
| 326 | | if (this.currentLayer) { |
|---|
| 327 | | // set this.currentLayer to null before destroying the layer, to |
|---|
| 328 | | // avoid the problems with a layer with no map object in the |
|---|
| 329 | | // moveLayerToTop function below |
|---|
| 330 | | var toDestroy = this.currentLayer; |
|---|
| 331 | | this.currentLayer = null; |
|---|
| 332 | | toDestroy.destroy(); |
|---|
| 333 | | } |
|---|
| 334 | | |
|---|
| | 468 | * Create the vector layer. |
|---|
| | 469 | */ |
|---|
| | 470 | createLayer: function() { |
|---|
| | 471 | var layer = new OpenLayers.Layer.Vector( |
|---|
| | 472 | OpenLayers.Util.createUniqueID("mf.ediding"), { |
|---|
| | 473 | strategies: [this.createStrategy()], |
|---|
| | 474 | styleMap: this.createStyleMap(), |
|---|
| | 475 | displayInLayerSwitcher: false |
|---|
| | 476 | }); |
|---|
| | 477 | layer.events.register( |
|---|
| | 478 | "featureselected", this, this.onFeatureselected |
|---|
| | 479 | ); |
|---|
| | 480 | layer.events.register( |
|---|
| | 481 | "featureunselected", this, this.onFeatureunselected |
|---|
| | 482 | ); |
|---|
| | 483 | layer.events.register( |
|---|
| | 484 | "featureremoved", this, this.onFeatureremoved |
|---|
| | 485 | ); |
|---|
| | 486 | layer.events.register( |
|---|
| | 487 | "featuremodified", this, this.onFeaturemodified |
|---|
| | 488 | ); |
|---|
| | 489 | return layer; |
|---|
| | 490 | }, |
|---|
| | 491 | |
|---|
| | 492 | /** |
|---|
| | 493 | * Method: destroyLayer |
|---|
| | 494 | * Destroy the vector layer. |
|---|
| | 495 | */ |
|---|
| | 496 | destroyLayer: function() { |
|---|
| | 497 | var layer = this.layer; |
|---|
| | 498 | if (layer) { |
|---|
| | 499 | layer.destroy(); |
|---|
| | 500 | this.layer = null; |
|---|
| | 501 | } |
|---|
| | 502 | }, |
|---|
| | 503 | |
|---|
| | 504 | /** |
|---|
| | 505 | * Method: createStyleMap |
|---|
| | 506 | * Create a style map for the vector layer. |
|---|
| | 507 | * |
|---|
| | 508 | * Returns: |
|---|
| | 509 | * {<OpenLayer.StyleMap>} The style map. |
|---|
| | 510 | */ |
|---|
| | 511 | createStyleMap: function() { |
|---|
| | 512 | var styleMap = new OpenLayers.StyleMap(); |
|---|
| 362 | | |
|---|
| 363 | | config.strategy.autoDestroy = false; |
|---|
| 364 | | config.protocol.autoDestroy = false; |
|---|
| 365 | | |
|---|
| 366 | | this.currentLayer = new OpenLayers.Layer.Vector(layer, { |
|---|
| 367 | | strategies: [config.strategy], |
|---|
| 368 | | protocol: config.protocol, |
|---|
| 369 | | format: config.format, |
|---|
| 370 | | styleMap: styleMap, |
|---|
| 371 | | displayInLayerSwitcher: false |
|---|
| 372 | | }); |
|---|
| 373 | | |
|---|
| 374 | | this.map.addLayer(this.currentLayer); |
|---|
| 375 | | |
|---|
| 376 | | this.currentLayer.events.on({ |
|---|
| 377 | | 'featuremodified': function(obj) { |
|---|
| 378 | | var feature = obj.feature; |
|---|
| 379 | | if (feature.state != OpenLayers.State.INSERT) { |
|---|
| 380 | | feature.state = OpenLayers.State.UPDATE; |
|---|
| 381 | | } |
|---|
| 382 | | } |
|---|
| 383 | | }); |
|---|
| 384 | | |
|---|
| 385 | | var title, handler, iconCls; |
|---|
| 386 | | switch (config.featuretypes.geometry.type) { |
|---|
| 387 | | case OpenLayers.Geometry.Point: |
|---|
| 388 | | title = 'draw point'; |
|---|
| 389 | | handler = OpenLayers.Handler.Point; |
|---|
| 390 | | iconCls = 'drawpoint'; |
|---|
| 391 | | break; |
|---|
| 392 | | case OpenLayers.Geometry.Polygon: |
|---|
| 393 | | case OpenLayers.Geometry.MultiPolygon: |
|---|
| 394 | | title = 'draw polygon'; |
|---|
| 395 | | handler = OpenLayers.Handler.Polygon; |
|---|
| 396 | | iconCls = 'drawpolygon'; |
|---|
| 397 | | break; |
|---|
| 398 | | case OpenLayers.Geometry.LineString: |
|---|
| 399 | | case OpenLayers.Geometry.MultiLineString: |
|---|
| 400 | | title = 'draw line'; |
|---|
| 401 | | handler = OpenLayers.Handler.Path; |
|---|
| 402 | | iconCls = 'drawline'; |
|---|
| 403 | | break; |
|---|
| 404 | | } |
|---|
| 405 | | |
|---|
| 406 | | this.modifyControl = new OpenLayers.Control.ModifyFeature( |
|---|
| 407 | | this.currentLayer, |
|---|
| 408 | | { |
|---|
| 409 | | mode: OpenLayers.Control.ModifyFeature.RESHAPE | OpenLayers.Control.ModifyFeature.DRAG, |
|---|
| 410 | | title: 'select and modify a feature' |
|---|
| 411 | | } |
|---|
| 412 | | ); |
|---|
| 413 | | // the modify feature control's deactivate method calls selectControl.unselect |
|---|
| 414 | | // if a feature is being modified, this causes problem if that feature isn't |
|---|
| 415 | | // known by the vector layer |
|---|
| 416 | | this.modifyControl.layer.events.on({ |
|---|
| 417 | | featureremoved: function(obj) { |
|---|
| 418 | | if (obj.feature == this.feature) { |
|---|
| 419 | | this.feature = null; |
|---|
| 420 | | } |
|---|
| 421 | | }, |
|---|
| 422 | | scope: this.modifyControl |
|---|
| 423 | | }); |
|---|
| 424 | | |
|---|
| 425 | | this.drawFeatureControl = new OpenLayers.Control.DrawFeature( |
|---|
| 426 | | this.currentLayer, handler, { |
|---|
| 427 | | title: title, |
|---|
| 428 | | featureAdded: OpenLayers.Function.bind(function(feature) { |
|---|
| 429 | | feature.state = OpenLayers.State.INSERT; |
|---|
| 430 | | // because "featuresadded" has already been triggered in |
|---|
| 431 | | // Layer/Vector.js, we trigger it once more |
|---|
| 432 | | this.currentLayer.events.triggerEvent("featuresadded", |
|---|
| 433 | | {features: [feature]}); |
|---|
| 434 | | this.modifyControl.selectControl.select(feature); |
|---|
| 435 | | this.attributesEditingForm.getForm().loadRecord(this.attributesFormDefaults); |
|---|
| 436 | | this.modifyControl.activate(); |
|---|
| 437 | | }, this) |
|---|
| 438 | | }); |
|---|
| 439 | | |
|---|
| 440 | | // The following works around a bug in OpenLayers. When switching from the modify |
|---|
| 441 | | // feature control to the drawing feature control, the modify feature control |
|---|
| 442 | | // resets the vector layer's z-index to its value based on its index in the |
|---|
| 443 | | // layers array, by registering to the drawing feature control's activate |
|---|
| 444 | | // and deactivate events we set the vector layer's z-index appropriately. |
|---|
| 445 | | // FIXME this workaround must be removed once this is fixed in OpenLayers |
|---|
| 446 | | function moveLayerToTop(evt) { |
|---|
| 447 | | if (this.currentLayer && (!evt || !evt.property || evt.property == "order")) { |
|---|
| 448 | | var index = Math.max(this.currentLayer.map.Z_INDEX_BASE['Feature'] - 1, |
|---|
| 449 | | this.currentLayer.getZIndex()) + 1; |
|---|
| 450 | | this.currentLayer.setZIndex(index); |
|---|
| 451 | | } |
|---|
| 452 | | } |
|---|
| 453 | | this.drawFeatureControl.events.on({ |
|---|
| 454 | | activate: moveLayerToTop, |
|---|
| 455 | | deactivate: function() { |
|---|
| 456 | | if (this.currentLayer) { |
|---|
| 457 | | var index = this.currentLayer.getZIndex() - 1; |
|---|
| 458 | | if (index >= this.currentLayer.map.Z_INDEX_BASE['Feature']) { |
|---|
| 459 | | this.currentLayer.setZIndex(index); |
|---|
| 460 | | } else { |
|---|
| 461 | | this.currentLayer.map.setLayerZIndex(this.currentLayer, |
|---|
| 462 | | this.currentLayer.map.getLayerIndex(this.currentLayer)); |
|---|
| 463 | | } |
|---|
| 464 | | } |
|---|
| 465 | | }, |
|---|
| 466 | | scope: this |
|---|
| 467 | | }); |
|---|
| 468 | | this.map.events.on({ |
|---|
| 469 | | "changelayer": moveLayerToTop, |
|---|
| 470 | | "removelayer": moveLayerToTop, |
|---|
| 471 | | "scope": this |
|---|
| 472 | | }); |
|---|
| 473 | | |
|---|
| 474 | | this.getTopToolbar().addControl(this.modifyControl, { |
|---|
| 475 | | iconCls: 'modifyfeature', |
|---|
| 476 | | toggleGroup: 'map' |
|---|
| 477 | | }); |
|---|
| 478 | | this.getTopToolbar().addControl(this.drawFeatureControl, { |
|---|
| 479 | | iconCls: iconCls, |
|---|
| 480 | | toggleGroup: 'map' |
|---|
| 481 | | }); |
|---|
| 482 | | this.modifyControl.activate(); |
|---|
| 483 | | |
|---|
| | 538 | return styleMap; |
|---|
| | 539 | }, |
|---|
| | 540 | |
|---|
| | 541 | /** |
|---|
| | 542 | * Method: createStrategy |
|---|
| | 543 | * Create a BBOX strategy for the vector layer. |
|---|
| | 544 | * |
|---|
| | 545 | * Returns: |
|---|
| | 546 | * {<OpenLayers.Strategy.BBOX>} |
|---|
| | 547 | */ |
|---|
| | 548 | createStrategy: function() { |
|---|
| | 549 | return new OpenLayers.Strategy.BBOX({ |
|---|
| | 550 | autoActivate: false |
|---|
| | 551 | }); |
|---|
| | 552 | }, |
|---|
| | 553 | |
|---|
| | 554 | /** |
|---|
| | 555 | * Method: onFeatureselected |
|---|
| | 556 | * |
|---|
| | 557 | * Parameters: |
|---|
| | 558 | * obj - {Object} Object with a feature property |
|---|
| | 559 | */ |
|---|
| | 560 | onFeatureselected: function(obj) { |
|---|
| | 561 | var f = obj.feature; |
|---|
| | 562 | this.deleteBtn.enable(); |
|---|
| | 563 | this.selectInGrid(f); |
|---|
| | 564 | this.editAttributes(f); |
|---|
| | 565 | }, |
|---|
| | 566 | |
|---|
| | 567 | /** |
|---|
| | 568 | * Method: onFeatureunselected |
|---|
| | 569 | * |
|---|
| | 570 | * Parameters: |
|---|
| | 571 | * obj - {Object} Object with a feature property |
|---|
| | 572 | */ |
|---|
| | 573 | onFeatureunselected: function(obj) { |
|---|
| | 574 | this.deleteBtn.disable(); |
|---|
| | 575 | this.unselectInGrid(); |
|---|
| | 576 | this.form.getForm().reset(); |
|---|
| | 577 | this.form.setDisabled(true); |
|---|
| | 578 | }, |
|---|
| | 579 | |
|---|
| | 580 | /** |
|---|
| | 581 | * Method: createStore |
|---|
| | 582 | * Create the store containing the edited features. |
|---|
| | 583 | */ |
|---|
| | 584 | createStore: function(config) { |
|---|
| | 585 | this.destroyStore(); |
|---|
| 496 | | |
|---|
| 497 | | var layerStoreMediator = new mapfish.widgets.data.LayerStoreMediator({ |
|---|
| | 597 | store.on("add", this.updateCommitBtnState, this); |
|---|
| | 598 | store.on("remove", this.updateCommitBtnState, this); |
|---|
| | 599 | store.on("clear", this.updateCommitBtnState, this); |
|---|
| | 600 | store.on("load", this.updateGridSelection, this); |
|---|
| | 601 | this.store = store; |
|---|
| | 602 | }, |
|---|
| | 603 | |
|---|
| | 604 | /** |
|---|
| | 605 | * Method: destroyStore |
|---|
| | 606 | * Destroy the feature store. |
|---|
| | 607 | */ |
|---|
| | 608 | destroyStore: function() { |
|---|
| | 609 | var store = this.store; |
|---|
| | 610 | if (store) { |
|---|
| | 611 | // for unknown reason this method is in Ext's API |
|---|
| | 612 | // doc, use it anyway as it's the safest method to |
|---|
| | 613 | // unregister listeners registered in the store |
|---|
| | 614 | store.destroy(); |
|---|
| | 615 | this.store = null; |
|---|
| | 616 | } |
|---|
| | 617 | }, |
|---|
| | 618 | |
|---|
| | 619 | /** |
|---|
| | 620 | * Method: updateCommitBtnState |
|---|
| | 621 | * Enable or disable the commit button based on whether there |
|---|
| | 622 | * are records or store in the store. |
|---|
| | 623 | */ |
|---|
| | 624 | updateCommitBtnState: function(store) { |
|---|
| | 625 | this.commitBtn.setDisabled(!(store.getCount() > 0)); |
|---|
| | 626 | }, |
|---|
| | 627 | |
|---|
| | 628 | /** |
|---|
| | 629 | * Method: updateGridSelection |
|---|
| | 630 | * Make the selection in the grid reflect what's selected in |
|---|
| | 631 | * the layer. |
|---|
| | 632 | */ |
|---|
| | 633 | updateGridSelection: function(store, records, options) { |
|---|
| | 634 | for (var i = 0; i < records.length; i++) { |
|---|
| | 635 | var feature = records[i].data.feature; |
|---|
| | 636 | if (OpenLayers.Util.indexOf( |
|---|
| | 637 | this.layer.selectedFeatures, feature) >= 0) { |
|---|
| | 638 | this.selectInGrid(feature); |
|---|
| | 639 | } |
|---|
| | 640 | } |
|---|
| | 641 | }, |
|---|
| | 642 | |
|---|
| | 643 | /** |
|---|
| | 644 | * Method: createModifyFeatureControl |
|---|
| | 645 | * Create a modify feature control. |
|---|
| | 646 | */ |
|---|
| | 647 | createModifyFeatureControl: function() { |
|---|
| | 648 | this.destroyModifyFeatureControl(); |
|---|
| | 649 | var ctrl = new OpenLayers.Control.ModifyFeature(this.layer, { |
|---|
| | 650 | mode: OpenLayers.Control.ModifyFeature.RESHAPE | |
|---|
| | 651 | OpenLayers.Control.ModifyFeature.DRAG, |
|---|
| | 652 | title: OpenLayers.i18n("mf.editing.selectModifyFeature") |
|---|
| | 653 | }); |
|---|
| | 654 | this.getTopToolbar().addControl(ctrl, { |
|---|
| | 655 | iconCls: 'modifyfeature', |
|---|
| | 656 | toggleGroup: 'map' |
|---|
| | 657 | }); |
|---|
| | 658 | ctrl.activate(); |
|---|
| | 659 | this.modifyFeatureControl = ctrl; |
|---|
| | 660 | }, |
|---|
| | 661 | |
|---|
| | 662 | /** |
|---|
| | 663 | * Method: destroyModifyFeatureControl |
|---|
| | 664 | * Destroy the modify feature control. |
|---|
| | 665 | */ |
|---|
| | 666 | destroyModifyF |
|---|