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

« back to all changes in this revision

Viewing changes to gis/dhis-gis-geostat/mfbase/mapfish/widgets/print/Base.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 core/PrintProtocol.js
 
22
 * @requires core/Util.js
 
23
 * @requires OpenLayers/Control/DragFeature.js
 
24
 * @requires OpenLayers/Layer/Vector.js
 
25
 * @requires OpenLayers/Feature/Vector.js
 
26
 * @requires OpenLayers/Geometry/Polygon.js
 
27
 */
 
28
 
 
29
Ext.namespace('mapfish.widgets');
 
30
Ext.namespace('mapfish.widgets.print');
 
31
 
 
32
/**
 
33
 * Class: mapfish.widgets.print.Base
 
34
 * Base class for the Ext panels used to communicate with the print module,
 
35
 * automatically take the layers from the given {<OpenLayers.Map>} instance.
 
36
 *
 
37
 * If you put this panel directly inside an {Ext.TabPanel} or an accordion, it
 
38
 * will activate/desactivate automaticaly. But if you have more complex
 
39
 * layouts like windows or print panel in a panel in an {Ext.TabPanel}, it's
 
40
 * your responsability to call enable() and disable().
 
41
 *
 
42
 * Inherits from:
 
43
 * - {Ext.Panel}
 
44
 */
 
45
 
 
46
/**
 
47
 * Constructor: mapfish.widgets.print.Base
 
48
 *
 
49
 * Parameters:
 
50
 * config - {Object} Config object
 
51
 */
 
52
 
 
53
mapfish.widgets.print.Base = Ext.extend(Ext.Panel, {
 
54
    /**
 
55
     * APIProperty: map
 
56
     * {<OpenLayers.Map>} - The OpenLayers Map object.
 
57
     */
 
58
    map: null,
 
59
 
 
60
    /**
 
61
     * APIProperty: overrides
 
62
     * {Object} the map that specify the print module overrides for each layers.
 
63
     *    They can be used of changing the OL layer's bahaviors for the print
 
64
     *   module. See the documentation in {<mapfish.PrintProtocol>}.
 
65
     */
 
66
    overrides: null,
 
67
 
 
68
    /**
 
69
     * APIProperty: configUrl
 
70
     * {String} - The URL to access .../config.json. Either this property or
 
71
     *            config must be set.
 
72
     */
 
73
    configUrl: null,
 
74
 
 
75
    /**
 
76
     * APIProperty: config
 
77
     * {Object} - The response from .../config.json. Either this property or
 
78
     *            configUrl must be set.
 
79
     */
 
80
    config: null,
 
81
 
 
82
    /**
 
83
     * APIProperty: layerTree
 
84
     * {<mapfish.widgets.LayerTree>} - An optional layer tree. Needed only if you
 
85
      *                                want to display legends.
 
86
     */
 
87
    layerTree: null,
 
88
 
 
89
    /**
 
90
     * APIProperty: grids
 
91
     * {Object} - An optional dictionary of {Ext.grid.GridPanel}. Needed only
 
92
     *            if you want to display search results. Can be function
 
93
     *            (returning the dictionary) that will be called each time the
 
94
     *            information is needed.
 
95
     */
 
96
    grids: null,
 
97
 
 
98
    /**
 
99
     * APIProperty: serviceParams
 
100
     * {Object} Additional params to send in the print service Ajax calls. Can
 
101
     *          be used to set the "locale" parameter.
 
102
     */
 
103
    serviceParams: null,
 
104
 
 
105
    /**
 
106
     * Property: pageDrag
 
107
     * {<OpenLayers.Control.DragFeature>} - The control to move the extent.
 
108
     */
 
109
    pageDrag: null,
 
110
 
 
111
    /**
 
112
     * Property: rotateHandle
 
113
     * {<OpenLayers.Feature.Vector>} - The handle used to rotate the page.
 
114
     */
 
115
    rotateHandle: null,
 
116
 
 
117
    /**
 
118
     * Property: layer
 
119
     * {<OpenLayers.Layer.Vector>} - The layer to draw the extent
 
120
     */
 
121
    layer: null,
 
122
 
 
123
    /**
 
124
     * Property: mask
 
125
     * {Ext.LoadingMask} - The mask used when loading the configuration or
 
126
     *                     when generating the PDF
 
127
     */
 
128
    mask: null,
 
129
 
 
130
    layout: 'fit',
 
131
 
 
132
    /**
 
133
     * Method: initComponent
 
134
     * Overrides super-class initComponent method. Put in place the handlers
 
135
     * for the showing/hidding of the panel. Then call the createComponent
 
136
     *  method
 
137
     */
 
138
    initComponent: function() {
 
139
        mapfish.widgets.print.Base.superclass.initComponent.call(this);
 
140
 
 
141
        this.addEvents("configloaded");
 
142
 
 
143
        //for accordion
 
144
        this.on('expand', this.setUp, this);
 
145
        this.on('collapse', this.tearDown, this);
 
146
 
 
147
        //for tabs
 
148
        this.on('activate', this.setUp, this);
 
149
        this.on('deactivate', this.tearDown, this);
 
150
 
 
151
        //for manual enable/disable
 
152
        this.on('enable', this.setUp, this);
 
153
        this.on('disable', this.tearDown, this);
 
154
 
 
155
        if (this.overrides == null) {
 
156
            this.overrides = {};
 
157
        }
 
158
 
 
159
        this.on('render', function() {
 
160
            var mask = this.mask = new Ext.LoadMask(this.getEl(), {
 
161
                msg: OpenLayers.Lang.translate('mf.print.loadingConfig')
 
162
            });
 
163
            if (this.config == null) {
 
164
                mask.show();
 
165
            }
 
166
        }, this);
 
167
 
 
168
        if (this.config == null) {
 
169
            mapfish.PrintProtocol.getConfiguration(this.configUrl,
 
170
                    this.configReceived, this.configFailed, this, this.serviceParams);
 
171
        } else {
 
172
            this.fillComponent();
 
173
        }
 
174
    },
 
175
 
 
176
    configReceived: function(config) {
 
177
        if (this.mask) {
 
178
            this.mask.hide();
 
179
        }
 
180
        this.config = config;
 
181
        this.fillComponent();
 
182
        this.doLayout();
 
183
        // for the case the widget was opened before the config was received
 
184
        this.setUp();
 
185
        this.fireEvent("configloaded");
 
186
    },
 
187
 
 
188
    configFailed: function() {
 
189
        this.add({
 
190
            border: false,
 
191
            region: 'center',
 
192
            html: OpenLayers.Lang.translate('mf.print.serverDown')
 
193
        });
 
194
        this.doLayout();
 
195
        if (this.mask) {
 
196
            this.mask.hide();
 
197
        }
 
198
        this.config = false;
 
199
    },
 
200
 
 
201
    /**
 
202
     * Method: isReallyVisible
 
203
     *
 
204
     * One cannot trust Ext's isVisible method. If a panel is within another
 
205
     * panel that is not visible it returns true which is utterly wrong.
 
206
     *
 
207
     * Returns:
 
208
     * {Boolean} True of the panel is really visible
 
209
     */
 
210
    isReallyVisible: function() {
 
211
        if (!this.isVisible() || !this.body.isVisible(true)) return false;
 
212
        var result = true;
 
213
        this.bubble(function(component) {
 
214
            return result = result &&
 
215
                component.isVisible() &&
 
216
                (!component.body || component.body.isVisible());
 
217
        }, this);
 
218
        return result;
 
219
    },
 
220
 
 
221
    /**
 
222
     * Method: onShowEvent
 
223
     *
 
224
     * Called when the panel is activated.
 
225
     */
 
226
    setUp: function() {
 
227
        if (!this.disabled && this.isReallyVisible() && this.config && !this.layer) {
 
228
            this.map.addLayer(this.getOrCreateLayer());
 
229
            this.pageDrag.activate();
 
230
        }
 
231
    },
 
232
 
 
233
    /**
 
234
     * Method: onHideEvent
 
235
     *
 
236
     * Called when the panel is de-activated.
 
237
     */
 
238
    tearDown: function() {
 
239
        if (this.config && this.pageDrag && this.layer) {
 
240
            this.pageDrag.destroy();
 
241
            this.pageDrag = null;
 
242
 
 
243
            this.removeRotateHandle();
 
244
            this.layer.removeFeatures(this.layer.features);
 
245
            this.layer.destroy();
 
246
            this.layer = null;
 
247
        }
 
248
    },
 
249
 
 
250
    /**
 
251
     * Method: getOrCreateLayer
 
252
     *
 
253
     * If not already done, creates the layer used to represent the pages to
 
254
     * print.
 
255
     * Returns:
 
256
     * {<OpenLayers.Layer.Vector>}  
 
257
     */
 
258
    getOrCreateLayer: function() {
 
259
        if (!this.layer) {
 
260
            var self = this;
 
261
 
 
262
            this.layer = new OpenLayers.Layer.Vector("Print" + this.getId(), {
 
263
                displayInLayerSwitcher: false,
 
264
                calculateInRange: function() {
 
265
                    return true;
 
266
                }
 
267
            });
 
268
 
 
269
            this.pageDrag = new OpenLayers.Control.DragFeature(this.layer);
 
270
            this.map.addControl(this.pageDrag);
 
271
            var curFeature = null;
 
272
            this.pageDrag.onStart = function(feature) {
 
273
                OpenLayers.Control.DragFeature.prototype.onStart.apply(this, arguments);
 
274
                curFeature = feature;
 
275
                if (feature.attributes.rotate) {
 
276
                    self.pageRotateStart(feature);
 
277
                } else {
 
278
                    self.pageDragStart(feature);
 
279
                }
 
280
            };
 
281
            this.pageDrag.onDrag = function(feature) {
 
282
                OpenLayers.Control.DragFeature.prototype.onDrag.apply(this, arguments);
 
283
                if (!feature) feature = curFeature;
 
284
                if (feature.attributes.rotate) {
 
285
                    self.pageRotated(feature);
 
286
                }
 
287
            };
 
288
            this.pageDrag.onComplete = function(feature) {
 
289
                OpenLayers.Control.DragFeature.prototype.onComplete.apply(this, arguments);
 
290
                if (!feature) feature = curFeature;
 
291
                if (feature.attributes.rotate) {
 
292
                    self.pageRotateComplete(feature);
 
293
                } else {
 
294
                    self.pageDragComplete(feature);
 
295
                }
 
296
                curFeature = null;
 
297
            };
 
298
 
 
299
            this.afterLayerCreated();
 
300
        }
 
301
        return this.layer;
 
302
    },
 
303
 
 
304
    /**
 
305
     * Method: pageRotateStart
 
306
     *
 
307
     * Called when the user starts to move the rotate handle.
 
308
     *
 
309
     * Parameters:
 
310
     * feature - {<OpenLayers.Feature.Vector>} The rotate handle.
 
311
     */
 
312
    pageRotateStart: function(feature) {
 
313
    },
 
314
 
 
315
    /**
 
316
     * Method: pageRotated
 
317
     *
 
318
     * Called when rotate handle is being moved.
 
319
     *
 
320
     * Parameters:
 
321
     * feature - {<OpenLayers.Feature.Vector>} The rotate handle.
 
322
     */
 
323
    pageRotated: function(feature) {
 
324
        var center = feature.attributes.center;
 
325
        var pos = feature.geometry;
 
326
        var angle = Math.atan2(pos.x - center.x, pos.y - center.y) * 180 / Math.PI;
 
327
        var page = feature.attributes.page;
 
328
        page.attributes.rotation = angle;
 
329
        page.geometry.rotate(feature.attributes.prevAngle - angle, center);
 
330
        this.layer.drawFeature(page);
 
331
        this.setCurRotation(Math.round(angle));
 
332
        feature.attributes.prevAngle = angle;
 
333
    },
 
334
 
 
335
    /**
 
336
     * Method: pageRotateComplete
 
337
     *
 
338
     * Called when rotate handle is being released.
 
339
     *
 
340
     * Parameters:
 
341
     * feature - {<OpenLayers.Feature.Vector>} The rotate handle.
 
342
     */
 
343
    pageRotateComplete: function(feature) {
 
344
        //put back the rotate handle at the page's edge
 
345
        this.createRotateHandle(feature.attributes.page);
 
346
    },
 
347
 
 
348
    /**
 
349
     * Method: pageDragStart
 
350
     *
 
351
     * Called when we start editing a page.
 
352
     *
 
353
     * Parameters:
 
354
     * feature - {<OpenLayers.Feature.Vector>} The selected page.
 
355
     */
 
356
    pageDragStart: function(feature) {
 
357
        this.removeRotateHandle();
 
358
    },
 
359
 
 
360
    /**
 
361
     * Method: removeRotateHandle
 
362
     *
 
363
     * Remove the rotation handle, if any.
 
364
     */
 
365
    removeRotateHandle: function() {
 
366
        if (this.rotateHandle) {
 
367
            this.rotateHandle.destroy();
 
368
            this.rotateHandle = null;
 
369
        }
 
370
    },
 
371
 
 
372
    /**
 
373
     * Method: pageDragComplete
 
374
     *
 
375
     * Called when we stop editing a page.
 
376
     *
 
377
     * Parameters:
 
378
     * feature - {<OpenLayers.Feature.Vector>} The selected page.
 
379
     */
 
380
    pageDragComplete: function(feature) {
 
381
        if (this.getCurLayout().rotation) {
 
382
            this.createRotateHandle(feature);
 
383
        }
 
384
    },
 
385
 
 
386
    /**
 
387
     * Method: createRotateHandle
 
388
     *
 
389
     * Create the handle used to rotate the page.
 
390
     *
 
391
     * Parameters:
 
392
     * feature - {<OpenLayers.Feature.Vector>} The selected page.
 
393
     */
 
394
    createRotateHandle: function(feature) {
 
395
        this.removeRotateHandle();
 
396
 
 
397
        var firstPoint = feature.geometry.components[0].components[2];
 
398
        var secondPoint = feature.geometry.components[0].components[3];
 
399
        var lon = (firstPoint.x + secondPoint.x) / 2;
 
400
        var lat = (firstPoint.y + secondPoint.y) / 2;
 
401
        var rotatePoint = new OpenLayers.Geometry.Point(lon, lat);
 
402
        var center = this.getCenterRectangle(feature);
 
403
        this.rotateHandle = new OpenLayers.Feature.Vector(rotatePoint, {
 
404
            rotate: true,
 
405
            page: feature,
 
406
            center: {x: center[0], y: center[1]},
 
407
            prevAngle: feature.attributes.rotation
 
408
        });
 
409
        this.layer.addFeatures(this.rotateHandle);
 
410
    },
 
411
 
 
412
    /**
 
413
     * Method: createRectangle
 
414
     *
 
415
     * Create the feature representing a page to print.
 
416
     *
 
417
     * Parameters:
 
418
     * center - {<OpenLayers.LonLat>} The center of the rectangle.
 
419
     * scale - {Integer} The page's scale
 
420
     * layout - {Object} The current layout object from the configuration.
 
421
     * rotation - {float} The current rotation in degrees.
 
422
     *
 
423
     * Returns:
 
424
     * {<OpenLayers.Feature.Vector>}
 
425
     */
 
426
    createRectangle: function(center, scale, layout, rotation) {
 
427
        var extent = this.getExtent(center, scale, layout);
 
428
        var rect = extent.toGeometry();
 
429
        rect.rotate(-rotation, {x:center.lon, y:center.lat});
 
430
        var feature = new OpenLayers.Feature.Vector(rect, {rotation: rotation});
 
431
        this.layer.addFeatures(feature);
 
432
 
 
433
        return feature;
 
434
    },
 
435
 
 
436
    /**
 
437
     * Method: getCenterRectangle
 
438
     *
 
439
     * Parameters:
 
440
     * rectangle - {<OpenLayers.Feature.Vector>}
 
441
     *
 
442
     * Returns:
 
443
     * {<OpenLayers.LonLat>} The center of the rectangle.
 
444
     */
 
445
    getCenterRectangle: function(rectangle) {
 
446
        var center = rectangle.geometry.getBounds().getCenterLonLat();
 
447
        return [center.lon, center.lat];
 
448
    },
 
449
 
 
450
    /**
 
451
     * Method: getExtent
 
452
     *
 
453
     * Compute the page's extent.
 
454
     *
 
455
     * Parameters:
 
456
     * center - {<OpenLayers.LonLat>} The center of the rectangle.
 
457
     * scale - {Integer} The page's scale
 
458
     * layout - {Object} The current layout object from the configuration.
 
459
     *
 
460
     * Returns:
 
461
     * {<OpenLayers.Bounds>}
 
462
     */
 
463
    getExtent: function(center, scale, layout) {
 
464
        var unitsRatio = OpenLayers.INCHES_PER_UNIT[this.map.baseLayer.units];
 
465
 
 
466
        var size = layout.map;
 
467
        var w = size.width / 72.0 / unitsRatio * scale / 2.0;
 
468
        var h = size.height / 72.0 / unitsRatio * scale / 2.0;
 
469
 
 
470
        return new OpenLayers.Bounds(
 
471
                center.lon - w,
 
472
                center.lat - h,
 
473
                center.lon + w,
 
474
                center.lat + h);
 
475
    },
 
476
 
 
477
    /**
 
478
     * Finds the best scale to use for the given layout in function of the map's
 
479
     * extent.
 
480
     *
 
481
     * Parameters:
 
482
     * layout - {Object} The current layout object from the configuration.
 
483
     *
 
484
     * Returns:
 
485
     * {Integer} The best scale
 
486
     */
 
487
    fitScale: function(layout) {
 
488
        var availsTxt = this.config.scales;
 
489
        if (availsTxt.length == 0) return;
 
490
        var avails = [];
 
491
        for (var i = 0; i < availsTxt.length; ++i) {
 
492
            avails.push(parseFloat(availsTxt[i].value));
 
493
        }
 
494
        avails.sort(function(a, b) {
 
495
            return a - b;
 
496
        });
 
497
 
 
498
        var bounds = this.map.getExtent();
 
499
        var unitsRatio = OpenLayers.INCHES_PER_UNIT[this.map.baseLayer.units];
 
500
        var size = layout.map;
 
501
 
 
502
        var targetScale = Math.min(bounds.getWidth() / size.width * 72.0 * unitsRatio,
 
503
                bounds.getHeight() / size.height * 72.0 * unitsRatio);
 
504
 
 
505
        var nearestScale = avails[0];
 
506
        for (var j = 1; j < avails.length; ++j) {
 
507
            if (avails[j] <= targetScale) {
 
508
                nearestScale = avails[j];
 
509
            } else {
 
510
                break;
 
511
            }
 
512
        }
 
513
 
 
514
        return nearestScale;
 
515
    },
 
516
 
 
517
    /**
 
518
     * Method: print
 
519
     *
 
520
     * Do the actual printing.
 
521
     */
 
522
    print: function() {
 
523
        //we don't want the layer used for the extent to be printed, don't we?
 
524
        this.overrides[this.layer.name] = {visibility: false};
 
525
 
 
526
        var printCommand = new mapfish.PrintProtocol(this.map, this.config,
 
527
                this.overrides, this.getCurDpi(), this.serviceParams);
 
528
        if (this.layerTree) {
 
529
            this.addLegends(printCommand.spec);
 
530
        }
 
531
        if (this.grids) {
 
532
            this.addGrids(printCommand.spec);
 
533
        }
 
534
        this.fillSpec(printCommand);
 
535
 
 
536
        this.mask.msg = OpenLayers.Lang.translate('mf.print.generatingPDF');
 
537
        this.mask.show();
 
538
        printCommand.createPDF(
 
539
            function() { //success
 
540
                this.mask.hide();
 
541
            },
 
542
            function(request) { //failure
 
543
                if(request.getURL) {
 
544
                    Ext.Msg.alert(OpenLayers.Lang.translate('mf.information'),
 
545
                        OpenLayers.Lang.translate('mf.print.popupBlocked') +
 
546
                        '<br />' +
 
547
                        '<a href="' + request.getURL + '" target="_blanc">' +
 
548
                        request.getURL+'</a>');
 
549
                } else {
 
550
                    Ext.Msg.alert(OpenLayers.Lang.translate('mf.error'),
 
551
                        OpenLayers.Lang.translate('mf.print.unableToPrint'));
 
552
                }
 
553
                this.mask.hide();
 
554
            }, this);
 
555
    },
 
556
 
 
557
    /**
 
558
     * Method: addGrids
 
559
     *
 
560
     * Add the grids' data to the given spec.
 
561
     *
 
562
     * Parameters:
 
563
     * spec - {Object} The print spec to fill.
 
564
     */
 
565
    addGrids: function(spec) {
 
566
        var grids = this.grids;
 
567
        if (grids && typeof grids == "function") {
 
568
            grids = grids();
 
569
        }
 
570
        if (grids) {
 
571
            for (var name in grids) {
 
572
                var grid = grids[name];
 
573
                if (!grid) {
 
574
                    continue;
 
575
                }
 
576
                spec[name] = {};
 
577
                var specData = spec[name].data = [];
 
578
                var specCols = spec[name].columns = [];
 
579
                var columns = grid.getColumnModel();
 
580
                var store = grid.getStore();
 
581
                for (var j = 0; j < columns.getColumnCount(); ++j) {
 
582
                    if (!columns.isHidden(j)) {
 
583
                        specCols.push(columns.getDataIndex(j));
 
584
                    }
 
585
                }
 
586
                store.each(function(record) {
 
587
                    var hash = {};
 
588
                    for (var key in record.data) {
 
589
                        var val = record.data[key];
 
590
                        if (val != null) {
 
591
                            if (val.CLASS_NAME && val.CLASS_NAME == 'OpenLayers.Feature.Vector') {
 
592
                                val = new OpenLayers.Format.WKT().write(val);
 
593
                            }
 
594
                            hash[key] = val;
 
595
                        }
 
596
                    }
 
597
                    specData.push(hash);
 
598
                }, this);
 
599
            }
 
600
        }
 
601
    },
 
602
 
 
603
    /**
 
604
     * Method: addLegends
 
605
     *
 
606
     * Add the layerTree's legends to the given spec.
 
607
     *
 
608
     * Parameters:
 
609
     * spec - {Object} The print spec to fill.
 
610
     */
 
611
    addLegends: function(spec) {
 
612
        var legends = spec.legends = [];
 
613
 
 
614
        function addLayer(layerNode) {
 
615
            var layerInfo = {
 
616
                name: layerNode.attributes.printText || layerNode.attributes.text,
 
617
                icon:  mapfish.Util.relativeToAbsoluteURL(layerNode.attributes.icon)
 
618
            };
 
619
            var classesInfo = layerInfo.classes = [];
 
620
            layerNode.eachChild(function(classNode) {
 
621
                classesInfo.push({
 
622
                    name: classNode.attributes.printText || classNode.attributes.text,
 
623
                    icon:  mapfish.Util.relativeToAbsoluteURL(classNode.attributes.icon)
 
624
                });
 
625
            }, this);
 
626
            legends.push(layerInfo);
 
627
        }
 
628
 
 
629
        function goDeep(root) {
 
630
            root.eachChild(function(node) {
 
631
                var attr = node.attributes;
 
632
                if (attr.checked && attr.layerNames) {
 
633
                    addLayer(node);
 
634
                } else {
 
635
                    goDeep(node);
 
636
                }
 
637
            }, this);
 
638
        }
 
639
        goDeep(this.layerTree.getRootNode());
 
640
    },
 
641
 
 
642
    /**
 
643
     * Method: getLayoutForName
 
644
     *
 
645
     * Finds the layout object from the configuration by it's name.
 
646
     *
 
647
     * Parameters:
 
648
     * layoutName - {String}
 
649
     *
 
650
     * Returns:
 
651
     * {Object}  
 
652
     */
 
653
    getLayoutForName: function(layoutName) {
 
654
        var layouts = this.config.layouts;
 
655
        for (var i = 0; i < layouts.length; ++i) {
 
656
            var cur = layouts[i];
 
657
            if (cur.name == layoutName) {
 
658
                return cur;
 
659
            }
 
660
        }
 
661
    },
 
662
 
 
663
    /**
 
664
     * Method: createScaleCombo
 
665
     */
 
666
    createScaleCombo: function() {
 
667
        var scaleStore = new Ext.data.JsonStore({
 
668
            root: "scales",
 
669
            fields: ['name', 'value'],
 
670
            data: this.config
 
671
        });
 
672
 
 
673
        return new Ext.form.ComboBox({
 
674
            fieldLabel: OpenLayers.Lang.translate('mf.print.scale'),
 
675
            store: scaleStore,
 
676
            displayField: 'name',
 
677
            valueField: 'value',
 
678
            typeAhead: false,
 
679
            mode: 'local',
 
680
            id: 'scale_' + this.getId(),
 
681
            hiddenId: 'scaleId_' + this.getId(),
 
682
            hiddenName: "scale",
 
683
            name: "scale",
 
684
            editable: false,
 
685
            triggerAction: 'all',
 
686
            value: this.config.scales[this.config.scales.length - 1].value
 
687
        });
 
688
    },
 
689
 
 
690
    /**
 
691
     * Method: createDpiCombo
 
692
     */
 
693
    createDpiCombo: function(name) {
 
694
        if (this.config.dpis.length > 1) {
 
695
            var dpiStore = new Ext.data.JsonStore({
 
696
                root: "dpis",
 
697
                fields: ['name', 'value'],
 
698
                data: this.config
 
699
            });
 
700
 
 
701
            return {
 
702
                fieldLabel: OpenLayers.Lang.translate('mf.print.dpi'),
 
703
                xtype: 'combo',
 
704
                store: dpiStore,
 
705
                displayField: 'name',
 
706
                valueField: 'value',
 
707
                typeAhead: false,
 
708
                mode: 'local',
 
709
                id: 'dpi_' + this.getId(),
 
710
                hiddenId: 'dpiId_' + this.getId(),
 
711
                hiddenName: name,
 
712
                name: name,
 
713
                editable: false,
 
714
                triggerAction: 'all',
 
715
                value: this.config.dpis[0].value
 
716
            };
 
717
        } else {
 
718
            return {
 
719
                xtype: 'hidden',
 
720
                name: name,
 
721
                value: this.config.dpis[0].value
 
722
            };
 
723
        }
 
724
    },
 
725
 
 
726
    /**
 
727
     * Method: createLayoutCombo
 
728
     */
 
729
    createLayoutCombo: function(name) {
 
730
        if (this.config.layouts.length > 1) {
 
731
            var layoutStore = new Ext.data.JsonStore({
 
732
                root: "layouts",
 
733
                fields: ['name'],
 
734
                data: this.config
 
735
            });
 
736
 
 
737
            return new Ext.form.ComboBox({
 
738
                fieldLabel: OpenLayers.Lang.translate('mf.print.layout'),
 
739
                store: layoutStore,
 
740
                displayField: 'name',
 
741
                valueField: 'name',
 
742
                typeAhead: false,
 
743
                mode: 'local',
 
744
                id: 'layout_' + this.getId(),
 
745
                hiddenId: 'layoutId_' + this.getId(),
 
746
                hiddenName: name,
 
747
                name: name,
 
748
                editable: false,
 
749
                triggerAction: 'all',
 
750
                value: this.config.layouts[0].name
 
751
            });
 
752
        } else {
 
753
            return new Ext.form.Hidden({
 
754
                name: name,
 
755
                value: this.config.layouts[0].name
 
756
            });
 
757
        }
 
758
    },
 
759
 
 
760
    /**
 
761
     * Method: createRotationTextField
 
762
     *
 
763
     * Creates a text field for editing the rotation. Only if the config
 
764
     * has at least one layout allowing rotations, otherwise, returns null.
 
765
     */
 
766
    createRotationTextField: function() {
 
767
        var layouts = this.config.layouts;
 
768
        var hasRotation = false;
 
769
        for (var i = 0; i < layouts.length && ! hasRotation; ++i) {
 
770
            hasRotation = layouts[i].rotation;
 
771
        }
 
772
        if (hasRotation) {
 
773
            var num = /^-?[0-9]+$/;
 
774
            return new Ext.form.TextField({
 
775
                fieldLabel: OpenLayers.Lang.translate('mf.print.rotation'),
 
776
                name: 'rotation',
 
777
                value: '0',
 
778
                maskRe: /^[-0-9]$/,
 
779
                msgTarget: 'side',
 
780
                validator: function(v) {
 
781
                    return num.test(v) ? true : "Not a number";
 
782
                }
 
783
            });
 
784
        } else {
 
785
            return null;
 
786
        }
 
787
    },
 
788
 
 
789
    /**
 
790
     * Method: fillComponent
 
791
     *
 
792
     * Called by initComponent to create the component's sub-elements. To be
 
793
     * implemented by child classes.
 
794
     */
 
795
    fillComponent: null,
 
796
 
 
797
    /**
 
798
     * Method: afterLayerCreated
 
799
     *
 
800
     * Called just after the layer has been created. To be implemented by child
 
801
     * classes.
 
802
     */
 
803
    afterLayerCreated: null,
 
804
 
 
805
    /**
 
806
     * Method: getCurDpi
 
807
     *
 
808
     * Returns the user selected DPI. To be implemented by child classes.
 
809
     */
 
810
    getCurDpi: null,
 
811
 
 
812
    /**
 
813
     * Method: fillSpec
 
814
     * Add the page definitions and set the other parameters. To be implemented
 
815
     * by child classes.
 
816
     *
 
817
     * Parameters:
 
818
     * printCommand - {<mapfish.PrintProtocol>} The print definition to fill.
 
819
     */
 
820
    fillSpec: null,
 
821
 
 
822
    /**
 
823
     * Method: getCurLayout
 
824
     *
 
825
     * Returns:
 
826
     * {Object} - The current layout config object
 
827
     */
 
828
    getCurLayout: null,
 
829
 
 
830
    /**
 
831
     * Method: setCurRotation
 
832
     *
 
833
     * Called when the rotation of the current page has been changed.
 
834
     *
 
835
     * Parameters:
 
836
     * rotation - {float}
 
837
     */
 
838
    setCurRotation: null
 
839
});