[Commits] r1876 - in core/trunk/geoext: examples lib lib/GeoExt/plugins tests tests/lib/GeoExt/plugins

commits at geoext.org commits at geoext.org
Tue Feb 9 15:49:35 CET 2010


Author: ahocevar
Date: 2010-02-09 15:49:35 +0100 (Tue, 09 Feb 2010)
New Revision: 1876

Added:
   core/trunk/geoext/examples/print-extent.html
   core/trunk/geoext/examples/print-extent.js
   core/trunk/geoext/lib/GeoExt/plugins/PrintExtent.js
   core/trunk/geoext/tests/lib/GeoExt/plugins/PrintExtent.html
Modified:
   core/trunk/geoext/lib/GeoExt.js
   core/trunk/geoext/tests/list-tests.html
Log:
added a MapPanel plugin for interactively modifying the print extent. Thanks elemoine for refactoring this to become a plugin instead of a component. p=elemoine,me, r=elemoine,me (closes #204)

Added: core/trunk/geoext/examples/print-extent.html
===================================================================
--- core/trunk/geoext/examples/print-extent.html	                        (rev 0)
+++ core/trunk/geoext/examples/print-extent.html	2010-02-09 14:49:35 UTC (rev 1876)
@@ -0,0 +1,35 @@
+<html>
+    <head>
+        <title>GeoExt PrintExtent Example</title>
+
+        <script type="text/javascript" src="http://extjs.cachefly.net/ext-2.2.1/adapter/ext/ext-base.js"></script>
+        <script type="text/javascript" src="http://extjs.cachefly.net/ext-2.2.1/ext-all.js"></script>
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/resources/css/ext-all.css" />
+        <link rel="stylesheet" type="text/css" href="http://extjs.cachefly.net/ext-2.2.1/examples/shared/examples.css" />
+        <script src="http://www.openlayers.org/dev/OpenLayers.js"></script>
+        <script type="text/javascript" src="../lib/GeoExt.js"></script>
+
+        <script type="text/javascript" src="print-extent.js"></script>
+        
+        <!-- The script below will load the capabilities of the print service
+             and save them into the global printCapabilities variable. Instead
+             of this, the PrintProvider can be configured with a url and take
+             care of fetching the capabilities. -->
+        <script type="text/javascript" src="http://demo.opengeo.org/geoserver/pdf/info.json?var=printCapabilities"></script>
+
+    </head>
+    <body>
+        <h1>Setting the Print Extent on the Map Interactively</h1>
+        <p>This example shows the how to set the bounds of a printable PDF
+        interactively with a dynamic print extent rectangle. It requires
+        the <a href="http://trac.mapfish.org/trac/mapfish/wiki/PrintModuleInstallation">MapFish</a>
+        or <a href="http://geoserver.org/display/GEOS/Printing+2.0+HOWTO">GeoServer</a>
+        print module.</p>
+        <p>Drag one of the handles to control the scale. Grab one of the
+        corner handles at its edge to rotate the extent. Hold the SHIFT key to
+        rotate in 45° increments only. Drag the extent rectangle to change the
+        center.</p>
+        <p>The js is not minified so it is readable. See <a href="print-extent.js">print-extent.js</a>.</p>
+        <div id="content"></div>
+    </body>
+</html>

Added: core/trunk/geoext/examples/print-extent.js
===================================================================
--- core/trunk/geoext/examples/print-extent.js	                        (rev 0)
+++ core/trunk/geoext/examples/print-extent.js	2010-02-09 14:49:35 UTC (rev 1876)
@@ -0,0 +1,51 @@
+ /**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
+ * Published under the BSD license.
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
+ * of the license.
+ */
+
+/** api: example[print-extent]
+ *  Setting the Print Extent interactively
+ *  --------------------------------------
+ *  Using the PrintExtent component to interactively change scale, center and
+ *  rotation of a print page.
+ */
+
+var mapPanel, printProvider;
+
+Ext.onReady(function() {
+    // The printProvider that connects us to the print service
+    printProvider = new GeoExt.data.PrintProvider({
+        method: "GET", // "POST" recommended for production use
+        capabilities: printCapabilities, // from the info.json script in the html
+        customParams: {
+            mapTitle: "Printing Demo",
+            comment: "This is a map printed from GeoExt."
+        }
+    });
+
+    // The map we want to print, with the PrintExtent added as item.
+    mapPanel = new GeoExt.MapPanel({
+        renderTo: "content",
+        width: 450,
+        height: 320,
+        layers: [new OpenLayers.Layer.WMS("Tasmania", "http://demo.opengeo.org/geoserver/wms",
+            {layers: "topp:tasmania_state_boundaries"}, {singleTile: true})],
+        center: [146.56, -41.56],
+        zoom: 6,
+        plugins: [
+            new GeoExt.plugins.PrintExtent({
+                printProvider: printProvider
+            })
+        ],
+        bbar: [{
+            text: "Create PDF",
+            handler: function() {
+                // the PrintExtent plugin is the mapPanel's 1st plugin
+                mapPanel.plugins[0].print();
+            }
+        }]
+    });
+});

Added: core/trunk/geoext/lib/GeoExt/plugins/PrintExtent.js
===================================================================
--- core/trunk/geoext/lib/GeoExt/plugins/PrintExtent.js	                        (rev 0)
+++ core/trunk/geoext/lib/GeoExt/plugins/PrintExtent.js	2010-02-09 14:49:35 UTC (rev 1876)
@@ -0,0 +1,336 @@
+/**
+ * Copyright (c) 2008-2009 The Open Source Geospatial Foundation
+ * 
+ * Published under the BSD license.
+ * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text
+ * of the license.
+ */
+Ext.namespace("GeoExt.plugins")
+
+/** api: (define)
+ *  module = GeoExt.plugins
+ *  class = PrintExtent
+ */
+
+/** api: example
+ *  Sample code to create a MapPanel with a PrintExtent, and print it
+ *  immediately:
+ * 
+ *  .. code-block:: javascript
+ *
+ *      var printExtent = new GeoExt.plugins.PrintExtent({
+ *          printProvider: new GeoExt.data.PrintProvider({
+ *              capabilities: printCapabilities
+ *          })
+ *      });
+ *     
+ *      var mapPanel = new GeoExt.MapPanel({
+ *          border: false,
+ *          renderTo: "div-id",
+ *          layers: [new OpenLayers.Layer.WMS("Tasmania", "http://demo.opengeo.org/geoserver/wms",
+ *              {layers: "topp:tasmania_state_boundaries"}, {singleTile: true})],
+ *          center: [146.56, -41.56],
+ *          zoom: 6,
+ *          plugins: printExtent
+ *      });
+ *
+ *      // print the map
+ *      printExtent.print();
+ */
+
+/** api: constructor
+ *  .. class:: PrintExtent
+ * 
+ *  Provides a way to show and modify the extents of print pages on the map. It
+ *  uses a layer to render the page extent and handle features of print pages,
+ *  and provides a control to modify them. Must be set as a plugin to a
+ *  :class:`GeoExt.MapPanel`.
+ */
+
+GeoExt.plugins.PrintExtent = function(config) {
+    config = config || {};
+
+    Ext.apply(this, config);
+    this.initialConfig = config;
+
+    if(!this.pages) {
+        this.pages = [new GeoExt.data.PrintPage({
+            printProvider: this.printProvider
+        })];
+    }
+
+    if(!this.printProvider) {
+        this.printProvider = this.pages[0].printProvider;
+    }
+};
+
+GeoExt.plugins.PrintExtent.prototype = {
+
+    /** private: initialConfig
+     *  ``Object`` Holds the initial config object passed to the
+     *  constructor.
+     */
+    initialConfig: null,
+
+    /** api: config[printProvider]
+     *  :class:`GeoExt.data.PrintProvider` The print provider this form
+     *  is connected to. Optional if pages are provided.
+     */
+    /** api: property[printProvider]
+     *  :class:`GeoExt.data.PrintProvider` The print provider this form
+     *  is connected to. Read-only.
+     */
+    printProvider: null,
+    
+    /** private: property[mapPanel]
+     *  ``OpenLayers.Map`` The map the layer and control are added to.
+     */
+    map: null,
+    
+    /** api: config[layer]
+     *  ``OpenLayers.Layer.Vector`` The layer used to render extent and handle
+     *  features to. Optional, will be created if not provided.
+     */
+    /** private: property[layer]
+     *  ``OpenLayers.Layer.Vector`` The layer used to render extent and handle
+     *  features to.
+     */
+    layer: null,
+    
+    /** private: property[control]
+     *  ``OpenLayers.Control.TransformFeature`` The control used to change
+     *      extent, center, rotation and scale.
+     */
+    control: null,
+    
+    /** api: config[pages]
+     *  Array of :class:`GeoExt.data.PrintPage` The pages that this form
+     *  controls. Optional. If not provided, it will be created with one page
+     *  that fits the current map extent.
+     *  
+     *  .. note:: All pages must use the same PrintProvider.
+     */
+    /** api: property[pages]
+     *  Array of :class:`GeoExt.data.PrintPage` The pages that this component
+     *  controls. Read-only.
+     */
+    pages: null,
+
+    /** api: property[page]
+     *  :class:`GeoExt.data.PrintPage` The page currently set for
+     *  transformation.
+     */
+    page: null,
+
+    /** api: method[print]
+     *  :param options: ``Object`` Options to send to the PrintProvider's
+     *      print method. See :ref:`GeoExt.data.PrintProvider.print`.
+     *  
+     *  Prints all pages as shown on the map.
+     */
+    print: function(options) {
+        this.printProvider.print(this.map, this.pages, options);
+    },
+
+    /** private: method[init]
+     *  :param mapPanel: class:`GeoExt.MapPanel`
+     *  
+     *  Initializes the plugin.
+     */
+    init: function(mapPanel) {
+        this.map = mapPanel.map;
+        mapPanel.on("destroy", this.onMapPanelDestroy, this);
+        this.setUp();
+    },
+
+    /** api: method[setUp]
+     *  Sets up the plugin, initializing the ``OpenLayers.Layer.Vector``
+     *  layer and ``OpenLayers.Control.TransformFeature``, and centering
+     *  the first page if no pages were specified in the configuration.
+     */
+    setUp: function() {
+        this.initLayer();
+
+        this.initControl();
+        this.map.addControl(this.control);
+        this.control.activate();
+
+        this.printProvider.on("layoutchange", this.updateBox, this);
+
+        if(!this.initialConfig.pages) {
+            this.page = this.pages[0];
+            var map = this.map;
+            if(map.getCenter()) {
+                this.fitPage();
+            } else {
+                map.events.register("moveend", this, function() {
+                    map.events.unregister("moveend", this, arguments.callee);
+                    this.fitPage();
+                });
+            }
+        }
+    },
+
+    /** private: method[tearDown]
+     *  Tear downs the plugin, removing the
+     *  ``OpenLayers.Control.TransformFeature`` control and
+     *  the ``OpenLayers.Layer.Vector`` layer.
+     */
+    tearDown: function() {
+        // note: we need to be extra cautious when destroying OpenLayers
+        // objects here (the tests will fail if we're not cautious anyway).
+        // We use obj.events to test whether an OpenLayers object is
+        // destroyed or not.
+
+        this.printProvider.un("layoutchange", this.updateBox, this);
+
+        var map = this.map;
+
+        var control = this.control;
+        if(control && control.events) {
+            control.deactivate();
+            if(map && map.events && control.map) {
+                map.removeControl(control);
+            }
+        }
+
+        var layer = this.layer;
+        if(layer && layer.events) {
+            for(var i=0, len=this.pages.length; i<len; ++i) {
+                var page = this.pages[i];
+                page.un("change", this.onPageChange, this);
+                layer.removeFeatures([page.feature]);
+            }
+        }
+
+        if(!this.initialConfig.layer &&
+           map && map.events &&
+           layer && layer.map) {
+            map.removeLayer(layer);
+        }
+    },
+
+    /** private: method[onMapPanelDestroy]
+     */
+    onMapPanelDestroy: function() {
+        this.tearDown();
+
+        var map = this.map;
+
+        var control = this.control;
+        if(map && map.events &&
+           control && control.events) {
+            control.destroy()
+        }
+
+        var layer = this.layer;
+        if(!this.initialConfig.layer &&
+           map && map.events &&
+           layer && layer.events) {
+            layer.destroy();
+        }
+
+        delete this.layer;
+        delete this.control;
+        delete this.page;
+        this.map = null;
+    },
+
+    /** private: method[initLayer]
+     */
+    initLayer: function() {
+        if(!this.layer) {
+            this.layer = new OpenLayers.Layer.Vector(null, {
+                displayInLayerSwitcher: false
+            });
+        }
+        for(var i=0, len=this.pages.length; i<len; ++i) {
+            var page = this.pages[i];
+            this.layer.addFeatures([page.feature]);
+            page.on("change", this.onPageChange, this);
+        }
+        if(!this.layer.map) {
+            this.map.addLayer(this.layer);
+        }
+    },
+    
+    /** private: method[initControl]
+     */
+    initControl: function() {
+        var pages = this.pages;
+
+        if(!this.control) {
+            this.control = new OpenLayers.Control.TransformFeature(this.layer, {
+                preserveAspectRatio: true,
+                eventListeners: {
+                    "beforesetfeature": function(e) {
+                        for(var i=0, len=this.pages.length; i<len; ++i) {
+                            if(this.pages[i].feature === e.feature) {
+                                this.page = this.pages[i];
+                                e.object.rotation = -this.pages[i].rotation;
+                                break;
+                            }
+                        }
+                    },
+                    "beforetransform": function(e) {
+                        var page = this.page;
+                        if(e.rotation) {
+                            if(this.printProvider.layout.get("rotation")) {
+                                page.setRotation(-e.object.rotation);
+                            } else {
+                                e.object.setFeature(page.feature);
+                            }
+                        } else {
+                            page.fit(e.object.box);
+                            var minScale = this.printProvider.scales.getAt(0);
+                            var maxScale = this.printProvider.scales.getAt(
+                                this.printProvider.scales.getCount() - 1);
+                            var boxBounds = e.object.box.geometry.getBounds();
+                            var pageBounds = page.feature.geometry.getBounds();
+                            var tooLarge = page.scale === minScale &&
+                                boxBounds.containsBounds(pageBounds);
+                            var tooSmall = page.scale === maxScale &&
+                                pageBounds.containsBounds(boxBounds);
+                            if(tooLarge === true || tooSmall === true) {
+                                this.updateBox();
+                            }
+                        }
+                        return false;
+                    },
+                    "transformcomplete": this.updateBox,
+                    scope: this
+                }
+            });
+        }
+    },
+
+    /** private: method[fitPage]
+     *  Fits the current print page to the map.
+     */
+    fitPage: function() {
+        if(this.page) {
+            this.page.fit(this.map);
+        }
+    },
+
+    /** private: method[updateBox]
+     *  Updates the transformation box after setting a new scale or
+     *  layout, or to fit the box to the extent feature after a tranform.
+     */
+    updateBox: function() {
+        var page = this.page;
+        this.control.setFeature(page.feature, {rotation: -page.rotation});
+    },
+
+    /** private: method[onPageChange]
+     *  Handler for a page's change event.
+     */
+    onPageChange: function(page, mods) {
+        if(mods.scale || this.control.feature !== page.feature) {
+            this.control.setFeature(page.feature, {rotation: -page.rotation});
+        }
+    }
+};
+
+/** api: ptype = gx_printextent */
+Ext.preg && Ext.preg("gx_printextent", GeoExt.plugins.PrintExtent);

Modified: core/trunk/geoext/lib/GeoExt.js
===================================================================
--- core/trunk/geoext/lib/GeoExt.js	2010-02-09 10:56:57 UTC (rev 1875)
+++ core/trunk/geoext/lib/GeoExt.js	2010-02-09 14:49:35 UTC (rev 1876)
@@ -112,6 +112,7 @@
             "GeoExt/data/PrintProvider.js",
             "GeoExt/plugins/PrintPageField.js",
             "GeoExt/plugins/PrintProviderField.js",
+            "GeoExt/plugins/PrintExtent.js",
             "GeoExt/widgets/PrintMapPanel.js"
         );
 

Added: core/trunk/geoext/tests/lib/GeoExt/plugins/PrintExtent.html
===================================================================
--- core/trunk/geoext/tests/lib/GeoExt/plugins/PrintExtent.html	                        (rev 0)
+++ core/trunk/geoext/tests/lib/GeoExt/plugins/PrintExtent.html	2010-02-09 14:49:35 UTC (rev 1876)
@@ -0,0 +1,156 @@
+<!DOCTYPE html>
+<html debug="true">
+  <head>
+    <script type="text/javascript" src="../../../../../openlayers/lib/OpenLayers.js"></script>
+    <script type="text/javascript" src="../../../../../ext/adapter/ext/ext-base.js"></script>
+    <script type="text/javascript" src="../../../../../ext/ext-all-debug.js"></script>
+    <script type="text/javascript" src="../../../../lib/GeoExt.js"></script>
+
+    <script type="text/javascript">
+        var printCapabilities = {"scales":[{"name":"1:25,000","value":"25000"},{"name":"1:50,000","value":"50000"},{"name":"1:100,000","value":"100000"},{"name":"1:200,000","value":"200000"},{"name":"1:500,000","value":"500000"},{"name":"1:1,000,000","value":"1000000"},{"name":"1:2,000,000","value":"2000000"},{"name":"1:4,000,000","value":"4000000"}],"dpis":[{"name":"75","value":"75"},{"name":"150","value":"150"},{"name":"300","value":"300"}],"layouts":[{"name":"A4 portrait","map":{"width":440,"height":483},"rotation":true},{"name":"Legal","map":{"width":440,"height":483},"rotation":false}],"printURL":"http://demo.opengeo.org/geoserver/pdf/print.pdf","createURL":"http://demo.opengeo.org/geoserver/pdf/create.json"};
+       
+        function test_ctor(t) {
+            t.plan(2);
+
+            var printProvider = new GeoExt.data.PrintProvider({
+                capabilities: printCapabilities
+            })
+            
+            var printExtent = new GeoExt.plugins.PrintExtent({
+                printProvider: printProvider
+            });
+            
+            t.ok(printExtent.printProvider === printProvider,
+                 "ctor sets printProvider in the instance");
+            t.ok(printExtent.pages[0] instanceof GeoExt.data.PrintPage,
+                 "ctor creates a PrintPage");
+        }
+        
+        function test_init(t) {
+            t.plan(2);
+
+            var printExtent = new GeoExt.plugins.PrintExtent({
+                printProvider: new GeoExt.data.PrintProvider({
+                    capabilities: printCapabilities
+                })
+            });
+
+            var mapPanel = new GeoExt.MapPanel({
+                renderTo: "mappanel",
+                width: 256,
+                height: 256,
+                map: {controls: []},
+                layers: [new OpenLayers.Layer("layer", {isBaseLayer: true})],
+                center: [146.56, -41.56],
+                zoom: 7,
+                plugins: [printExtent]
+            });
+            
+            t.ok(printExtent.map === mapPanel.map,
+                 "init sets mapPanel");
+            t.ok(mapPanel.hasListener("destroy"),
+                 "plugin listens to the panel destroy event");
+
+            mapPanel.destroy();
+         }
+
+        function test_destroy(t) {
+            t.plan(3);
+
+            var printExtent = new GeoExt.plugins.PrintExtent({
+                printProvider: new GeoExt.data.PrintProvider({
+                    capabilities: printCapabilities
+                })
+            });
+
+            var mapPanel = new GeoExt.MapPanel({
+                renderTo: "mappanel",
+                width: 256,
+                height: 256,
+                map: {controls: []},
+                layers: [new OpenLayers.Layer("layer", {isBaseLayer: true})],
+                center: [146.56, -41.56],
+                zoom: 7,
+                items: [printExtent]
+            });
+
+            mapPanel.destroy();
+            
+            t.eq(printExtent.layer, undefined,
+                 "layer destroyed");
+            t.eq(printExtent.control, undefined,
+                 "control destroyed.");
+            t.eq(printExtent.mapPanel, null,
+                 "mapPanel set to null");
+        }
+
+         function test_setUp(t) {
+            t.plan(4);
+
+            var printExtent = new GeoExt.plugins.PrintExtent({
+                printProvider: new GeoExt.data.PrintProvider({
+                    capabilities: printCapabilities
+                })
+            });
+
+            var mapPanel = new GeoExt.MapPanel({
+                renderTo: "mappanel",
+                width: 256,
+                height: 256,
+                map: {controls: []},
+                layers: [new OpenLayers.Layer("layer", {isBaseLayer: true})],
+                center: [146.56, -41.56],
+                zoom: 7,
+                plugins: [printExtent]
+            });
+
+            t.ok(printExtent.pages[0].getCenter().equals(mapPanel.map.getCenter()),
+                 "print page centered to map center");
+            t.ok(printExtent.layer.map == mapPanel.map,
+                 "auto-generated layer added to map.");
+            t.ok(printExtent.pages[0].feature.layer == printExtent.layer,
+                 "extent feature was added to the layer.");
+            t.ok(printExtent.control.map == mapPanel.map,
+                 "control created and added to map.");
+
+            mapPanel.destroy();
+        }
+
+        function test_tearDown(t) {
+            t.plan(3);
+ 
+            var printExtent = new GeoExt.plugins.PrintExtent({
+                printProvider: new GeoExt.data.PrintProvider({
+                    capabilities: printCapabilities
+                })
+            });
+
+            var mapPanel = new GeoExt.MapPanel({
+                renderTo: "mappanel",
+                width: 256,
+                height: 256,
+                map: {controls: []},
+                layers: [
+                    new OpenLayers.Layer("layer", {isBaseLayer: true})
+                ],
+                center: [146.56, -41.56],
+                zoom: 7,
+                plugins: [printExtent]
+            });
+
+            printExtent.tearDown();
+            
+            t.eq(mapPanel.map.layers.length, 1,
+                 "layer was removed.");
+            t.eq(mapPanel.map.controls.length, 0,
+                 "control was removed.");
+            t.eq(printExtent.pages[0].feature.layer, null,
+                 "feature was removed from the layer.")
+
+            mapPanel.destroy();
+        }
+    </script>
+  <body>
+    <div id="mappanel"></div>
+  </body>
+</html>

Modified: core/trunk/geoext/tests/list-tests.html
===================================================================
--- core/trunk/geoext/tests/list-tests.html	2010-02-09 10:56:57 UTC (rev 1875)
+++ core/trunk/geoext/tests/list-tests.html	2010-02-09 14:49:35 UTC (rev 1876)
@@ -17,6 +17,7 @@
   <li>lib/GeoExt/data/WMCReader.html</li>
   <li>lib/GeoExt/plugins/PrintPageField.html</li>
   <li>lib/GeoExt/plugins/PrintProviderField.html</li>
+  <li>lib/GeoExt/plugins/PrintExtent.html</li>
   <li>lib/GeoExt/widgets/Action.html</li>
   <li>lib/GeoExt/widgets/FeatureRenderer.html</li>
   <li>lib/GeoExt/widgets/LayerOpacitySlider.html</li>



More information about the Commits mailing list