2
* Copyright (C) 2007-2008 Camptocamp
4
* This file is part of MapFish Client
6
* MapFish Client is free software: you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation, either version 3 of the License, or
9
* (at your option) any later version.
11
* MapFish Client is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with MapFish Client. If not, see <http://www.gnu.org/licenses/>.
21
* @requires widgets/print/Base.js
24
Ext.namespace('mapfish.widgets');
25
Ext.namespace('mapfish.widgets.print');
28
* Class: mapfish.widgets.print.MultiPage
29
* Automatically takes the layers from the given {<OpenLayers.Map>} instance.
31
* If you put this panel directly inside an {Ext.TabPanel} or an accordion, it
32
* will activate/desactivate automaticaly. But if you have more complex
33
* layouts like windows or print panel in a panel in an {Ext.TabPanel}, it's
34
* your responsability to call enable() and disable().
37
* - {<mapfish.widgets.print.Base>}
41
* Constructor: mapfish.widgets.print.MultiPage
44
* config - {Object} Config object
47
mapfish.widgets.print.MultiPage = Ext.extend(mapfish.widgets.print.Base, {
49
* APIProperty: formConfig
50
* {Object} - The configuration options passed to the form that edits the
51
* options common to every pages.
53
* Can contain additional items for custom fields. Their values will be
54
* passed to the print service
59
* APIProperty: columns
60
* {Array} - The Additionnal columns for "per page" custom fields.
65
* APIProperty: zoomToExtentEnabled
66
* {Boolean} - If true, the map will try to always show the selected page's
67
* extent by zooming out if necessary.
69
zoomToExtentEnabled: true,
73
* {Ext.grid.EditorGridPanel} - The pages.
78
* Property: printButton
79
* {Ext.Button} - The "print" button.
84
* Property: freezeGeometryRefresh
86
* When true, the page's geometry is not refreshed when the data store is
89
freezeGeometryRefresh: false,
92
* Method: fillComponent
93
* Called by initComponent to create the component's sub-elements.
95
fillComponent: function() {
96
//The inner border layout (extra level used because the
97
//border layout doesn't allow to add components afterwards).
98
var innerPanel = this.add({
101
id: this.getId() + 'InnerPanel'
103
this.createGlobalForm(innerPanel);
104
this.createGrid(innerPanel);
110
//ugly hack to fix a FF3 bug that makes the inner panels miss-aligned
111
var buggyDiv = this.formPanel.getEl().parent();
112
buggyDiv.setStyle("position", "absolute");
113
setTimeout(function() {
114
buggyDiv.setStyle("position", "relative");
117
mapfish.widgets.print.Base.prototype.setUp.call(this);
122
* Method: createGlobalForm
124
* Create the form for editing the global parameters.
126
createGlobalForm: function(innerPanel) {
127
var formConfig = OpenLayers.Util.extend({
129
bodyStyle: 'padding: 7px 0 0 0;', //some space with the grid
131
//by default, we don't want borders for the inner form
134
id: this.getId() + "formPanel"
136
var formPanel = this.formPanel = new Ext.form.FormPanel(formConfig);
138
var layout = this.createLayoutCombo("layout");
139
if (this.config.layouts.length > 1) {
140
layout.on('select', this.layoutChanged, this);
142
formPanel.add(layout);
144
formPanel.add(this.createDpiCombo("dpi"));
146
this.printButton = formPanel.addButton({
147
text: OpenLayers.Lang.translate('mf.print.print'),
153
innerPanel.add(formPanel);
159
* Create the grid for editing pages' parameters.
161
createGrid: function(innerPanel) {
162
var scale = this.createScaleCombo();
163
scale.on('select', this.updateCurrentRectangle, this);
168
header: OpenLayers.Lang.translate('mf.print.scale'),
171
renderer: function(value) { return self.getScaleName(value); }
174
var rotation = this.createRotationTextField();
175
if (rotation != null) {
177
header: OpenLayers.Lang.translate('mf.print.rotation'),
178
dataIndex: 'rotation',
180
id: this.getId() + '_rotation',
181
hidden: !this.config.layouts[0].rotation
186
columns.push.apply(columns, this.columns);
190
for (var i = 0; i < columns.length; ++i) {
192
name: columns[i].dataIndex
195
var pages = new Ext.data.SimpleStore({
199
var grid = this.grid = new Ext.grid.EditorGridPanel({
202
id: this.getId() + 'PagesGrid',
204
enableColumnHide: false,
209
emptyText: OpenLayers.Lang.translate('mf.print.noPage')
211
sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
216
text: OpenLayers.Lang.translate('mf.print.addPage'),
218
handler: this.addPage
221
text: OpenLayers.Lang.translate('mf.print.remove'),
223
handler: this.removeSelected,
224
id: this.getId() + "_remove",
228
text: OpenLayers.Lang.translate('mf.print.clearAll'),
230
handler: this.clearPages
234
innerPanel.add(grid);
236
grid.getSelectionModel().addListener('selectionchange', this.selectionChanged, this);
237
grid.getStore().addListener('update', function (store, record, operation) {
238
if (!this.freezeGeometryRefresh) {
239
this.updateRectangle(record);
240
this.updatePrintLayerStyle();
243
grid.getStore().addListener('remove', function (store, record, index) {
244
this.layer.removeFeatures(record.data.rectangle);
245
this.removeRotateHandle();
246
if(store.getCount()==0) {
247
this.printButton.disable();
250
grid.getStore().addListener('clear', function () {
251
this.layer.removeFeatures(this.layer.features);
252
this.printButton.disable();
257
* Method: selectionChanged
259
* Called when the selection changed in the grid. Will highlight the
260
* selected page and make sure it's visible.
262
selectionChanged: function() {
263
this.updatePrintLayerStyle();
264
var removeButton = Ext.getCmp(this.getId() + '_remove');
265
var selected = this.grid.getSelectionModel().getSelected();
267
if(this.zoomToExtentEnabled) {
268
var bounds = selected.data.rectangle.geometry.getBounds().clone();
269
bounds.extend(this.map.getExtent());
270
this.map.zoomToExtent(bounds);
272
removeButton.enable();
274
var layoutData = this.getCurLayout();
275
if (layoutData.rotation) {
276
this.createRotateHandle(selected.data.rectangle);
279
removeButton.disable();
284
* Method: updatePrintLayerStyle
286
* Update the styles of the rectangle according the selected row in the
287
* grid. Makes sure the selected one is on top.
289
updatePrintLayerStyle: function() {
290
var selected = this.grid.getSelectionModel().getSelected();
292
for (var i = 0; i < this.layer.features.length; ++i) {
293
var feature = this.layer.features[i];
294
var isTheOne = feature.data.record == selected;
295
feature.style = OpenLayers.Feature.Vector.style[isTheOne ? 'select' : 'default'];
296
if (isTheOne && i != this.layer.features.length - 1) {
298
this.layer.removeFeatures(feature);
301
if (theOne) this.layer.addFeatures(theOne);
308
* Add a page that will fit the current extent.
310
addPage: function() {
311
var layoutData = this.getCurLayout();
312
var scale = this.fitScale(layoutData);
313
var feature = this.createRectangle(this.map.getCenter(), scale, layoutData, 0);
319
for (var i = 0; i < this.columns.length; ++i) {
320
var cur = this.columns[i].dataIndex;
321
if (newPage[cur] == null) {
326
var pages = this.grid.getStore();
327
var record = new pages.recordType(newPage);
329
feature.data.record = record;
330
this.grid.getSelectionModel().selectLastRow();
331
this.printButton.enable();
337
* Remove all the pages from the grid.
339
clearPages: function() {
340
this.grid.stopEditing();
341
this.grid.getStore().removeAll();
345
* Method: removeSelected
347
* Remove the selected page.
349
removeSelected: function() {
350
this.grid.stopEditing();
351
var record = this.grid.getSelectionModel().getSelected();
352
this.grid.getStore().remove(record);
356
* Method: layoutChanged
358
* Called when the layout changes. Will re-create all the
359
* rectangles and check if rotation is enabled.
361
layoutChanged: function() {
362
this.grid.getStore().each(function(record) {
363
this.updateRectangle(record);
365
this.updatePrintLayerStyle();
367
var cm = this.grid.getColumnModel();
368
var rotationIndex = cm.getIndexById(this.id + '_rotation');
369
if (rotationIndex >= 0) {
370
var layoutData = this.getCurLayout();
371
cm.setHidden(rotationIndex, !layoutData.rotation);
376
* Method: updateCurrentRectangle
378
* Re-create the rectangle for the currently selected page.
380
updateCurrentRectangle: function() {
381
this.updateRectangle(this.grid.getSelectionModel().getSelected());
382
this.updatePrintLayerStyle();
386
* Method: updateRectangle
388
* Re-create the rectangle for the given record.
391
* record - {Ext.data.Record} The page's record.
393
updateRectangle: function(record) {
394
this.grid.stopEditing();
395
this.layer.removeFeatures(record.data.rectangle);
396
var layoutData = this.getCurLayout();
397
var scale = record.get('scale');
398
var angle = layoutData.rotation ? record.get('rotation') : 0;
399
var center = record.data.rectangle.geometry.getBounds().getCenterLonLat();
400
var feature = this.createRectangle(center, scale, layoutData, angle);
401
feature.data.record = record;
402
record.data.rectangle = feature;
404
var sm = this.grid.getSelectionModel();
405
if (sm.getSelected() == record) {
406
if (layoutData.rotation) {
407
this.createRotateHandle(feature);
409
this.removeRotateHandle();
415
* Method: afterLayerCreated
417
* Called just after the layer has been created
419
afterLayerCreated: function() {
420
if (this.grid.getStore().getCount() != 0) {
421
this.grid.getStore().each(function(record) {
422
this.layer.addFeatures(record.data.rectangle);
424
this.updatePrintLayerStyle();
426
var sm = this.grid.getSelectionModel();
427
var selected = sm.getSelected();
428
if (selected && this.getCurLayout().rotation) {
429
this.createRotateHandle(selected.data.rectangle);
437
* Method: pageRotateStart
439
* Called when the user starts to move the rotate handle.
442
* feature - {<OpenLayers.Feature.Vector>} The rotate handle.
444
pageRotateStart: function(feature) {
445
mapfish.widgets.print.Base.prototype.pageRotateStart.call(this, feature);
446
this.grid.stopEditing();
450
* Method: pageDragStart
452
* Called when we start editing a page.
455
* feature - {<OpenLayers.Feature.Vector>} The selected page.
457
pageDragStart: function(feature) {
458
mapfish.widgets.print.Base.prototype.pageDragStart.call(this, feature);
460
//make sure the dragged page is selected in the grid (no zooming)
461
var prev = this.zoomToExtentEnabled;
462
var sm = this.grid.getSelectionModel();
463
if (sm.getSelected() != feature.data.record) {
464
this.zoomToExtentEnabled = false;
465
sm.selectRecords([feature.data.record]);
466
this.zoomToExtentEnabled = prev;
468
this.grid.stopEditing();
474
* Returns the user selected DPI.
476
getCurDpi: function() {
477
var values = this.formPanel.getForm().getValues();
478
return values["dpi"];
482
* Method: getCurLayoutName
484
getCurLayoutName: function() {
485
var values = this.formPanel.getForm().getValues();
486
return values['layout'];
490
* Method: getCurLayout
493
* {Object} - The current layout config object
495
getCurLayout: function() {
496
var layout = this.getCurLayoutName();
497
return this.getLayoutForName(layout);
501
* Method: setCurRotation
503
* Called when the rotation of the current page has been changed.
508
setCurRotation: function(rotation) {
509
var selected = this.grid.getSelectionModel().getSelected();
510
this.freezeGeometryRefresh = true;
511
selected.set('rotation', rotation);
512
this.freezeGeometryRefresh = false;
518
* Add the page definitions and set the other parameters.
521
* printCommand - {<mapfish.PrintProtocol>} The print definition to fill.
523
fillSpec: function(printCommand) {
524
var params = printCommand.spec;
525
var layout = this.getCurLayout();
527
//take care of the global values
528
this.formPanel.getForm().items.each(function(cur) {
529
params[cur.getName()] = cur.getValue();
532
//take care of the per-page values
533
this.grid.getStore().each(function(record) {
535
for (var key in record.data) {
536
if (key == 'rectangle') {
537
page.center = this.getCenterRectangle(record.data.rectangle);
538
} else if (key == 'rotation' && !layout.rotation) {
541
page[key] = record.data[key];
544
params.pages.push(page);
549
* Method: getScaleName
551
* Finds the scale name in function of its value.
554
* scaleValue - {Float}
557
* {String} The scale name.
559
getScaleName: function(scaleValue) {
560
var scales = this.config.scales;
561
for (var i = 0; i < scales.length; ++i) {
563
if (cur.value == scaleValue) {
570
Ext.reg('print-multi', mapfish.widgets.print.MultiPage);