~mortenoh/+junk/dhis2-detailed-import-export

« back to all changes in this revision

Viewing changes to gis/dhis-gis-geostat/mfbase/mapfish/widgets/print/MultiPage.js

  • Committer: larshelge at gmail
  • Date: 2009-03-03 16:46:36 UTC
  • Revision ID: larshelge@gmail.com-20090303164636-2sjlrquo7ib1gf7r
Initial check-in

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (C) 2007-2008  Camptocamp
 
3
 *
 
4
 * This file is part of MapFish Client
 
5
 *
 
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.
 
10
 *
 
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.
 
15
 *
 
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/>.
 
18
 */
 
19
 
 
20
/*
 
21
 * @requires widgets/print/Base.js
 
22
 */
 
23
 
 
24
Ext.namespace('mapfish.widgets');
 
25
Ext.namespace('mapfish.widgets.print');
 
26
 
 
27
/**
 
28
 * Class: mapfish.widgets.print.MultiPage
 
29
 * Automatically takes the layers from the given {<OpenLayers.Map>} instance.
 
30
 *
 
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().
 
35
 *
 
36
 * Inherits from:
 
37
 * - {<mapfish.widgets.print.Base>}
 
38
 */
 
39
 
 
40
/**
 
41
 * Constructor: mapfish.widgets.print.MultiPage
 
42
 *
 
43
 * Parameters:
 
44
 * config - {Object} Config object
 
45
 */
 
46
 
 
47
mapfish.widgets.print.MultiPage = Ext.extend(mapfish.widgets.print.Base, {
 
48
    /**
 
49
     * APIProperty: formConfig
 
50
     * {Object} - The configuration options passed to the form that edits the
 
51
     *            options common to every pages.
 
52
     *
 
53
     * Can contain additional items for custom fields. Their values will be
 
54
     * passed to the print service
 
55
     */
 
56
    formConfig: null,
 
57
 
 
58
    /**
 
59
     * APIProperty: columns
 
60
     * {Array} - The Additionnal columns for "per page" custom fields.
 
61
     */
 
62
    columns: null,
 
63
 
 
64
    /**
 
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.
 
68
     */
 
69
    zoomToExtentEnabled: true,
 
70
 
 
71
    /**
 
72
     * Property: grid
 
73
     * {Ext.grid.EditorGridPanel} - The pages.
 
74
     */
 
75
    grid: null,
 
76
 
 
77
    /**
 
78
     * Property: printButton
 
79
     * {Ext.Button} - The "print" button.
 
80
     */
 
81
    printButton: null,
 
82
 
 
83
    /**
 
84
     * Property: freezeGeometryRefresh
 
85
     *
 
86
     * When true, the page's geometry is not refreshed when the data store is
 
87
     * modified.
 
88
     */
 
89
    freezeGeometryRefresh: false,
 
90
 
 
91
    /**
 
92
     * Method: fillComponent
 
93
     * Called by initComponent to create the component's sub-elements.
 
94
     */
 
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({
 
99
            border: false,
 
100
            layout: 'border',
 
101
            id: this.getId() + 'InnerPanel'
 
102
        });
 
103
        this.createGlobalForm(innerPanel);
 
104
        this.createGrid(innerPanel);
 
105
    },
 
106
 
 
107
    setUp: function() {
 
108
        if (this.config) {
 
109
            if(Ext.isGecko3) {
 
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");
 
115
                }, 20);
 
116
            }
 
117
            mapfish.widgets.print.Base.prototype.setUp.call(this);
 
118
        }
 
119
    },
 
120
 
 
121
    /**
 
122
     * Method: createGlobalForm
 
123
     *
 
124
     * Create the form for editing the global parameters.
 
125
     */
 
126
    createGlobalForm: function(innerPanel) {
 
127
        var formConfig = OpenLayers.Util.extend({
 
128
            region: 'south',
 
129
            bodyStyle: 'padding: 7px 0 0 0;',  //some space with the grid
 
130
 
 
131
            //by default, we don't want borders for the inner form
 
132
            border: false,
 
133
            bodyBorder: false,
 
134
            id: this.getId() + "formPanel"
 
135
        }, this.formConfig);
 
136
        var formPanel = this.formPanel = new Ext.form.FormPanel(formConfig);
 
137
 
 
138
        var layout = this.createLayoutCombo("layout");
 
139
        if (this.config.layouts.length > 1) {
 
140
            layout.on('select', this.layoutChanged, this);
 
141
        }
 
142
        formPanel.add(layout);
 
143
 
 
144
        formPanel.add(this.createDpiCombo("dpi"));
 
145
 
 
146
        this.printButton = formPanel.addButton({
 
147
            text: OpenLayers.Lang.translate('mf.print.print'),
 
148
            scope: this,
 
149
            handler: this.print,
 
150
            disabled: true
 
151
        });
 
152
 
 
153
        innerPanel.add(formPanel);
 
154
    },
 
155
 
 
156
    /**
 
157
     * Method: createGrid
 
158
     *
 
159
     * Create the grid for editing pages' parameters.
 
160
     */
 
161
    createGrid: function(innerPanel) {
 
162
        var scale = this.createScaleCombo();
 
163
        scale.on('select', this.updateCurrentRectangle, this);
 
164
 
 
165
        var self = this;
 
166
        var columns = [
 
167
            {
 
168
                header: OpenLayers.Lang.translate('mf.print.scale'),
 
169
                dataIndex: 'scale',
 
170
                editor: scale,
 
171
                renderer: function(value) { return self.getScaleName(value); }
 
172
            }];
 
173
 
 
174
        var rotation = this.createRotationTextField();
 
175
        if (rotation != null) {
 
176
            columns.push({
 
177
                header: OpenLayers.Lang.translate('mf.print.rotation'),
 
178
                dataIndex: 'rotation',
 
179
                editor: rotation,
 
180
                id: this.getId() + '_rotation',
 
181
                hidden: !this.config.layouts[0].rotation
 
182
            });
 
183
        }
 
184
 
 
185
        if (this.columns) {
 
186
            columns.push.apply(columns, this.columns);
 
187
        }
 
188
 
 
189
        var pageFields = [];
 
190
        for (var i = 0; i < columns.length; ++i) {
 
191
            pageFields.push({
 
192
                name: columns[i].dataIndex
 
193
            });
 
194
        }
 
195
        var pages = new Ext.data.SimpleStore({
 
196
            fields: pageFields
 
197
        });
 
198
 
 
199
        var grid = this.grid = new Ext.grid.EditorGridPanel({
 
200
            region: 'center',
 
201
            border: false,
 
202
            id: this.getId() + 'PagesGrid',
 
203
            autoScroll: true,
 
204
            enableColumnHide: false,
 
205
            enableHdMenu: false,
 
206
            store: pages,
 
207
            viewConfig: {
 
208
                forceFit: true,
 
209
                emptyText: OpenLayers.Lang.translate('mf.print.noPage')
 
210
            },
 
211
            sm: new Ext.grid.RowSelectionModel({singleSelect:true}),
 
212
            clicksToEdit: 1,
 
213
            columns: columns,
 
214
            bbar: [
 
215
                {
 
216
                    text: OpenLayers.Lang.translate('mf.print.addPage'),
 
217
                    scope: this,
 
218
                    handler: this.addPage
 
219
                },
 
220
                {
 
221
                    text: OpenLayers.Lang.translate('mf.print.remove'),
 
222
                    scope: this,
 
223
                    handler: this.removeSelected,
 
224
                    id: this.getId() + "_remove",
 
225
                    disabled: true
 
226
                },
 
227
                {
 
228
                    text: OpenLayers.Lang.translate('mf.print.clearAll'),
 
229
                    scope: this,
 
230
                    handler: this.clearPages
 
231
                }
 
232
            ]
 
233
        });
 
234
        innerPanel.add(grid);
 
235
 
 
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();
 
241
            }
 
242
        }, this);
 
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();
 
248
            }
 
249
        }, this);
 
250
        grid.getStore().addListener('clear', function () {
 
251
            this.layer.removeFeatures(this.layer.features);
 
252
            this.printButton.disable();
 
253
        }, this);
 
254
    },
 
255
 
 
256
    /**
 
257
     * Method: selectionChanged
 
258
     *
 
259
     * Called when the selection changed in the grid. Will highlight the
 
260
     * selected page and make sure it's visible.
 
261
     */
 
262
    selectionChanged: function() {
 
263
        this.updatePrintLayerStyle();
 
264
        var removeButton = Ext.getCmp(this.getId() + '_remove');
 
265
        var selected = this.grid.getSelectionModel().getSelected();
 
266
        if (selected) {
 
267
            if(this.zoomToExtentEnabled) {
 
268
                var bounds = selected.data.rectangle.geometry.getBounds().clone();
 
269
                bounds.extend(this.map.getExtent());
 
270
                this.map.zoomToExtent(bounds);
 
271
            }
 
272
            removeButton.enable();
 
273
 
 
274
            var layoutData = this.getCurLayout();
 
275
            if (layoutData.rotation) {
 
276
                this.createRotateHandle(selected.data.rectangle);
 
277
            }
 
278
        } else {
 
279
            removeButton.disable();
 
280
        }
 
281
    },
 
282
 
 
283
    /**
 
284
     * Method: updatePrintLayerStyle
 
285
     *
 
286
     * Update the styles of the rectangle according the selected row in the
 
287
     * grid. Makes sure the selected one is on top.
 
288
     */
 
289
    updatePrintLayerStyle: function() {
 
290
        var selected = this.grid.getSelectionModel().getSelected();
 
291
        var theOne = null;
 
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) {
 
297
                theOne = feature;
 
298
                this.layer.removeFeatures(feature);
 
299
            }
 
300
        }
 
301
        if (theOne) this.layer.addFeatures(theOne);
 
302
        this.layer.redraw();
 
303
    },
 
304
 
 
305
    /**
 
306
     * Method: addPage
 
307
     *
 
308
     * Add a page that will fit the current extent.
 
309
     */
 
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);
 
314
        var newPage = {
 
315
            scale: scale,
 
316
            rotation: 0,
 
317
            rectangle: feature
 
318
        };
 
319
        for (var i = 0; i < this.columns.length; ++i) {
 
320
            var cur = this.columns[i].dataIndex;
 
321
            if (newPage[cur] == null) {
 
322
                newPage[cur] = "";
 
323
            }
 
324
        }
 
325
 
 
326
        var pages = this.grid.getStore();
 
327
        var record = new pages.recordType(newPage);
 
328
        pages.add(record);
 
329
        feature.data.record = record;
 
330
        this.grid.getSelectionModel().selectLastRow();
 
331
        this.printButton.enable();
 
332
    },
 
333
 
 
334
    /**
 
335
     * Method: clearPages
 
336
     *
 
337
     * Remove all the pages from the grid.
 
338
     */
 
339
    clearPages: function() {
 
340
        this.grid.stopEditing();
 
341
        this.grid.getStore().removeAll();
 
342
    },
 
343
 
 
344
    /**
 
345
     * Method: removeSelected
 
346
     *
 
347
     * Remove the selected page.
 
348
     */
 
349
    removeSelected: function() {
 
350
        this.grid.stopEditing();
 
351
        var record = this.grid.getSelectionModel().getSelected();
 
352
        this.grid.getStore().remove(record);
 
353
    },
 
354
 
 
355
    /**
 
356
     * Method: layoutChanged
 
357
     *
 
358
     * Called when the layout changes. Will re-create all the
 
359
     * rectangles and check if rotation is enabled.
 
360
     */
 
361
    layoutChanged: function() {
 
362
        this.grid.getStore().each(function(record) {
 
363
            this.updateRectangle(record);
 
364
        }, this);
 
365
        this.updatePrintLayerStyle();
 
366
 
 
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);
 
372
        }
 
373
    },
 
374
 
 
375
    /**
 
376
     * Method: updateCurrentRectangle
 
377
     *
 
378
     * Re-create the rectangle for the currently selected page.
 
379
     */
 
380
    updateCurrentRectangle: function() {
 
381
        this.updateRectangle(this.grid.getSelectionModel().getSelected());
 
382
        this.updatePrintLayerStyle();
 
383
    },
 
384
 
 
385
    /**
 
386
     * Method: updateRectangle
 
387
     *
 
388
     * Re-create the rectangle for the given record.
 
389
     *
 
390
     * Parameters:
 
391
     * record - {Ext.data.Record} The page's record.
 
392
     */
 
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;
 
403
 
 
404
        var sm = this.grid.getSelectionModel();
 
405
        if (sm.getSelected() == record) {
 
406
            if (layoutData.rotation) {
 
407
                this.createRotateHandle(feature);
 
408
            } else {
 
409
                this.removeRotateHandle();
 
410
            }
 
411
        }
 
412
    },
 
413
 
 
414
    /**
 
415
     * Method: afterLayerCreated
 
416
     *
 
417
     * Called just after the layer has been created
 
418
     */
 
419
    afterLayerCreated: function() {
 
420
        if (this.grid.getStore().getCount() != 0) {
 
421
            this.grid.getStore().each(function(record) {
 
422
                this.layer.addFeatures(record.data.rectangle);
 
423
            }, this);
 
424
            this.updatePrintLayerStyle();
 
425
 
 
426
            var sm = this.grid.getSelectionModel();
 
427
            var selected = sm.getSelected();
 
428
            if (selected && this.getCurLayout().rotation) {
 
429
                this.createRotateHandle(selected.data.rectangle);
 
430
            }
 
431
        } else {
 
432
            this.addPage();
 
433
        }
 
434
    },
 
435
 
 
436
    /**
 
437
     * Method: pageRotateStart
 
438
     *
 
439
     * Called when the user starts to move the rotate handle.
 
440
     *
 
441
     * Parameters:
 
442
     * feature - {<OpenLayers.Feature.Vector>} The rotate handle.
 
443
     */
 
444
    pageRotateStart: function(feature) {
 
445
        mapfish.widgets.print.Base.prototype.pageRotateStart.call(this, feature);
 
446
        this.grid.stopEditing();
 
447
    },
 
448
 
 
449
    /**
 
450
     * Method: pageDragStart
 
451
     *
 
452
     * Called when we start editing a page.
 
453
     *
 
454
     * Parameters:
 
455
     * feature - {<OpenLayers.Feature.Vector>} The selected page.
 
456
     */
 
457
    pageDragStart: function(feature) {
 
458
        mapfish.widgets.print.Base.prototype.pageDragStart.call(this, feature);
 
459
 
 
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;
 
467
        }
 
468
        this.grid.stopEditing();
 
469
    },
 
470
 
 
471
    /**
 
472
     * Method: getCurDpi
 
473
     *
 
474
     * Returns the user selected DPI.
 
475
     */
 
476
    getCurDpi: function() {
 
477
        var values = this.formPanel.getForm().getValues();
 
478
        return values["dpi"];
 
479
    },
 
480
 
 
481
    /**
 
482
     * Method: getCurLayoutName
 
483
     */
 
484
    getCurLayoutName: function() {
 
485
        var values = this.formPanel.getForm().getValues();
 
486
        return values['layout'];
 
487
    },
 
488
 
 
489
    /**
 
490
     * Method: getCurLayout
 
491
     *
 
492
     * Returns:
 
493
     * {Object} - The current layout config object
 
494
     */
 
495
    getCurLayout: function() {
 
496
        var layout = this.getCurLayoutName();
 
497
        return this.getLayoutForName(layout);
 
498
    },
 
499
 
 
500
    /**
 
501
     * Method: setCurRotation
 
502
     *
 
503
     * Called when the rotation of the current page has been changed.
 
504
     *
 
505
     * Parameters:
 
506
     * rotation - {Float}
 
507
     */
 
508
    setCurRotation: function(rotation) {
 
509
        var selected = this.grid.getSelectionModel().getSelected();
 
510
        this.freezeGeometryRefresh = true;
 
511
        selected.set('rotation', rotation);
 
512
        this.freezeGeometryRefresh = false;
 
513
    },
 
514
 
 
515
    /**
 
516
     * Method: fillSpec
 
517
     * 
 
518
     * Add the page definitions and set the other parameters.
 
519
     *
 
520
     * Parameters:
 
521
     * printCommand - {<mapfish.PrintProtocol>} The print definition to fill.
 
522
     */
 
523
    fillSpec: function(printCommand) {
 
524
        var params = printCommand.spec;
 
525
        var layout = this.getCurLayout();
 
526
 
 
527
        //take care of the global values
 
528
        this.formPanel.getForm().items.each(function(cur) {
 
529
            params[cur.getName()] = cur.getValue();
 
530
        }, this);
 
531
 
 
532
        //take care of the per-page values
 
533
        this.grid.getStore().each(function(record) {
 
534
            var page = {};
 
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) {
 
539
                    //no rotation
 
540
                } else {
 
541
                    page[key] = record.data[key];
 
542
                }
 
543
            }
 
544
            params.pages.push(page);
 
545
        }, this);
 
546
    },
 
547
 
 
548
    /**
 
549
     * Method: getScaleName
 
550
     *
 
551
     * Finds the scale name in function of its value.
 
552
     *
 
553
     * Parameters:
 
554
     * scaleValue - {Float}
 
555
     *
 
556
     * Returns:
 
557
     * {String} The scale name.
 
558
     */
 
559
    getScaleName: function(scaleValue) {
 
560
        var scales = this.config.scales;
 
561
        for (var i = 0; i < scales.length; ++i) {
 
562
            var cur = scales[i];
 
563
            if (cur.value == scaleValue) {
 
564
                return cur.name;
 
565
            }
 
566
        }
 
567
    }    
 
568
});
 
569
 
 
570
Ext.reg('print-multi', mapfish.widgets.print.MultiPage);