[Commits] r1548 - in sandbox/ahocevar/playground/ux/Printing: examples ux/data ux/plugins ux/widgets

commits at geoext.org commits at geoext.org
Fri Dec 4 01:23:43 CET 2009


Author: ahocevar
Date: 2009-12-04 01:23:43 +0100 (Fri, 04 Dec 2009)
New Revision: 1548

Modified:
   sandbox/ahocevar/playground/ux/Printing/examples/Printing.html
   sandbox/ahocevar/playground/ux/Printing/examples/Printing.js
   sandbox/ahocevar/playground/ux/Printing/ux/data/PrintProvider.js
   sandbox/ahocevar/playground/ux/Printing/ux/plugins/PrintLayoutField.js
   sandbox/ahocevar/playground/ux/Printing/ux/plugins/PrintPageAttributeField.js
   sandbox/ahocevar/playground/ux/Printing/ux/widgets/SimplePrint.js
Log:
fully working example - now move on to some refactoring

Modified: sandbox/ahocevar/playground/ux/Printing/examples/Printing.html
===================================================================
--- sandbox/ahocevar/playground/ux/Printing/examples/Printing.html	2009-12-03 20:59:09 UTC (rev 1547)
+++ sandbox/ahocevar/playground/ux/Printing/examples/Printing.html	2009-12-04 00:23:43 UTC (rev 1548)
@@ -17,6 +17,5 @@
         <script type="text/javascript" src="http://demo.mapfish.org/mapfishsample/1.2/print/info.json?var=printCapabilities"></script>
     </head>
     <body>
-        <a href="javascript:printProvider.print()">Print</a>
     </body>
 </html>

Modified: sandbox/ahocevar/playground/ux/Printing/examples/Printing.js
===================================================================
--- sandbox/ahocevar/playground/ux/Printing/examples/Printing.js	2009-12-03 20:59:09 UTC (rev 1547)
+++ sandbox/ahocevar/playground/ux/Printing/examples/Printing.js	2009-12-04 00:23:43 UTC (rev 1548)
@@ -1,4 +1,4 @@
-var printProvider;
+var printProvider, printForm;
 
 Ext.onReady(function() {
 
@@ -24,10 +24,9 @@
         new Vec(geom("LINESTRING(15 48, 16 47, 17 46)")),
         new Vec(geom("POINT(16 46)"))
     ]);
+    
     var mapPanel = new GeoExt.MapPanel({
-        renderTo: document.body,
-        width: 500,
-        height: 300,
+        region: "center",
         layers: [new OpenLayers.Layer.WMS("Global Imagery",
             "http://labs.metacarta.com/wms/vmap0",
             {layers: "basic"}), redline] ,
@@ -35,10 +34,56 @@
         zoom: 5
     });
     mapPanel.map.addLayer(redline);
-    var printForm = new GeoExt.ux.SimplePrint({
+    
+    var pageLayer = new OpenLayers.Layer.Vector(null, {displayInLayerSwitcher: false});
+    var pageFeature = new OpenLayers.Feature.Vector(null, {layout: null});
+    pageLayer.addFeatures(pageFeature);
+    var fit = false;
+    mapPanel.map.events.on({
+        "zoomend": function() {
+            if(!fit && mapPanel.map.getZoom() == mapPanel.initialConfig.zoom) {
+                fit = true;
+                printProvider.fitPage(pageFeature);
+                printProvider.updateHandle(printForm.handleFeature, pageFeature);
+            }
+        }
+    });
+    
+    printForm = new GeoExt.ux.SimplePrint({
         map: mapPanel,
         printProvider: printProvider,
-        renderTo: document.body
+        layer: pageLayer,
+        pageFeature: pageFeature,
+        bodyStyle: {padding: "5px"},
+        labelWidth: 65,
+        defaults: {width: 115},
+        region: "east",
+        width: 200,
+        items: [{
+            xtype: "textfield",
+            fieldLabel: "Title",
+            plugins: new GeoExt.ux.plugins.PrintPageAttributeField({
+                printProvider: this.printProvider,
+                attribute: "title",
+                pageFeature: pageFeature
+            })
+        }, {
+            xtype: "textarea",
+            fieldLabel: "Comment",
+            plugins: new GeoExt.ux.plugins.PrintPageAttributeField({
+                printProvider: this.printProvider,
+                attribute: "comment",
+                pageFeature: pageFeature
+            })
+        }]
     });
     
+    new Ext.Panel({
+        renderTo: document.body,
+        layout: "border",
+        width: 800,
+        height: 350,
+        items: [mapPanel, printForm]
+    });
+    
 });

Modified: sandbox/ahocevar/playground/ux/Printing/ux/data/PrintProvider.js
===================================================================
--- sandbox/ahocevar/playground/ux/Printing/ux/data/PrintProvider.js	2009-12-03 20:59:09 UTC (rev 1547)
+++ sandbox/ahocevar/playground/ux/Printing/ux/data/PrintProvider.js	2009-12-04 00:23:43 UTC (rev 1548)
@@ -248,9 +248,9 @@
         
         var pages;
         if(options.layer) {
-            pages = this.createPages(options.layer);
+            pages = this.createPages(options.layer, options.layout);
         } else {
-            var center = options.center  || map.getCenter();
+            var center = options.center || map.getCenter();
             if(center instanceof OpenLayers.LonLat) {
                 center = [center.lon, center.lat]
             }
@@ -271,7 +271,7 @@
 
         var layers = [];
         Ext.each(map.layers, function(layer){
-            if(layer != options.layer) {
+            if(layer !== options.layer) {
                 var enc = this.encodeLayer(layer);
                 enc && layers.push(enc);
             }
@@ -299,45 +299,75 @@
         }
     },
     
+    fitPage: function(feature) {
+        var id = feature.geometry.id;
+        feature.geometry = feature.layer.map.getExtent().toGeometry();
+        feature.geometry.id = id;
+        this.updateFeature(feature,
+            {scale: this.getBestScale(feature.layer.map)});
+    },
+    
+    updatePage: function(feature, handle) {
+        this.updateFeature(feature, null, handle);
+    },
+    
     /** api:method[getRotation]
      *  :param feature: ``OpenLayers.Feature.Vector``
+     *  :param handle: ``OpenLayers.Feature.Vector`` optional rotation handle.
+     *      If provided, the rotation of the feature relative to the handle
+     *      will be calculated. Otherwise, the rotation of the current feature
+     *      will be returned.
      *  :return: ``Float``
      *  
      *  Gets the rotation of a feature with a geometry originally created
      *  using ``OpenLayers.Bounds.toGeometry()``. Rotation is measured
      *  clockwise from North.
      */
-    getRotation: function(feature) {
+    getRotation: function(feature, handle) {
         if(!feature.geometry) {
             return 0;
         }
-        var points = feature.geometry.components[0].components;
-        var top = new OpenLayers.Geometry.LineString([points[2], points[3]]);
-        var right = new OpenLayers.Geometry.LineString([points[1], points[2]]);
+        var anglePoint = handle && handle.geometry ?
+            handle.geometry.getBounds().getCenterLonLat() :
+            this.getHandleLocation(feature);
         var center = feature.geometry.getBounds().getCenterLonLat();
-        var anglePoint = top.getBounds().getCenterLonLat();
         var dx = anglePoint.lon - center.lon;
         var dy = anglePoint.lat - center.lat;
-        return Math.atan2(dx, dy) * 180 / Math.PI;
+        return Math.round((Math.atan2(dx, dy) * 180 / Math.PI));
     },
     
+    /** private:method[getHandleLocation]
+     *  :param feature: ``OpenLayers.Feature.Vector``
+     *  :return: ``OpenLayers.LonLat``
+     *  
+     *  Calculates the scale/rotation handle location for a feature.
+     */
+    getHandleLocation: function(feature) {
+        var points = feature.geometry.components[0].components;
+        var top = new OpenLayers.Geometry.LineString([points[2], points[3]]);
+        return top.getBounds().getCenterLonLat();
+    },
+    
     /** private:method[createPages]
      *  :param layer: ``OpenLayers.Layer.Vector``
+     *  :param layout: ``String``
      *  :return: ``Array``
      *  
      *  Creates pages from the features of the provided layer.
      */
-    createPages: function(layer) {
+    createPages: function(layer, layout) {
         var pages = [];
         Ext.each(layer.features, function(feature) {
-            var center = feature.geometry.getBounds().getCenterLonLat();
-            pages.push({
-                mapTitle: feature.attributes.title || "",
-                comment: feature.attributes.comment || "",
-                center: [center.lon, center.lat],
-                scale: feature.attributes.scale,
-                rotation: feature.getRotation()
-            })
+            if(feature.attributes.layout == layout) {
+                var center = feature.geometry.getBounds().getCenterLonLat();
+                pages.push({
+                    mapTitle: feature.attributes.title || "",
+                    comment: feature.attributes.comment || "",
+                    center: [center.lon, center.lat],
+                    scale: feature.attributes.scale,
+                    rotation: feature.attributes.rotation
+                })
+            }
         }, this);
         return pages;
     },
@@ -374,7 +404,7 @@
         var unitsRatio = OpenLayers.INCHES_PER_UNIT[map.baseLayer.units];
         var w = size.width / 72 / unitsRatio * scale / 2;
         var h = size.height / 72 / unitsRatio * scale / 2;
-        var center = center || map.getCenter();
+        var center = center || map.getCenter() || new OpenLayers.LonLat(0, 0);
         return new OpenLayers.Bounds(center.lon - w, center.lat - h,
             center.lon + w, center.lat + h);
     },
@@ -396,7 +426,7 @@
         var layoutIndex = layoutName ?
             this.layouts.find("name", layoutName) : 0;
         var layout = this.layouts.getAt(layoutIndex);
-        var extent = map.getExtent();
+        var extent = map.getExtent() || map.baseLayer.maxExtent;
 
         var bounds, scale;
         this.scales.each(function(rec) {
@@ -409,35 +439,105 @@
         return scale;
     },
     
+    getScale: function(feature, handle) {
+        var layoutName = feature.attributes.layout;
+        var layout = this.layouts.getAt(
+            this.layouts.find("name", layoutName));
+        var dist = feature.geometry.getCentroid().distanceTo(handle.geometry);
+        scaleFits = [];
+        this.scales.each(function(rec){
+            var bounds = this.getLayoutBounds(
+                feature.layer.map,
+                rec.get("value"),
+                layout,
+                feature.geometry.getBounds().getCenterLonLat()
+            );
+            scaleFits.push(String(Math.abs((bounds.getHeight() / 2) - dist)));
+        }, this);
+        var min = scaleFits.concat().sort()[0];
+        var scale = this.scales.getAt(scaleFits.indexOf(min));
+        return scale.get("value");
+    },
+    
     /** api:function[updateFeature]
      *  :param feature: ``OpenLayers.Feature.Vector`` The feature to update.
      *  :param attributes: ``Object`` Attributes that will be applied to the
      *      feature, overriding existing attributes.
+     *  :param handle: ``OpenLayers.Feature.Vector`` Optional scale/rotation
+     *      handle. If provided, the handle will be used to change scale and
+     *      rotation of the feature.
      *      
      *  Updates a feature to represent a print page. The updated feature will
      *  have a ``scale``, ``layout`` and ``rotation`` attribute. The geometry
-     *  will be the bounds of the print page in map units.
+     *  will be the bounds of the print page in map units. Note that this
+     *  method only works for features that are on a layer which is on a map.
      */
-    updateFeature: function(feature, attributes) {
-        var map = feature.layer.map;
+    updateFeature: function(feature, attributes, handle) {
+        attributes = attributes || {};
+        if(handle && handle.geometry) {
+            attributes.rotation = this.getRotation(feature, handle);
+            attributes.scale = this.getScale(feature, handle);
+        }
+
+        var modified = false;
+        for(var i in attributes) {
+            if(attributes[i] != feature.attributes[i]) {
+                modified = true;
+            }
+        } 
+        if(!modified) {
+            return;
+        }
+        
+        attributes.rotation = (attributes.rotation == undefined) ?
+            this.getRotation(feature) :
+            attributes.rotation;
+        var layer = feature.layer;
+        var map = layer.map;
         var scale = attributes.scale || feature.attributes.scale;
-        var layout = attributes.layout || feature.attributes.layout;
-        var geom = this.getLayoutBounds(
-            map,
-            scale || this.getBestScale(map, layout),
-            layout,
-            feature.geometry ?
-                feature.geometry.getBounds().getCenterLonLat() :
-                map.getCenter()
-        );
-        attributes.rotation = attributes.rotation || feature.getRotation();
-        geom.rotate(-rotation, geom.getCentroid());
-        feature.geometry = geom;
+        var layoutName = attributes.layout || feature.attributes.layout;
+        var layout = this.layouts.getAt(this.layouts.find("name", layoutName));
+        if(layout) {
+            var geom = this.getLayoutBounds(
+                map,
+                scale || this.getBestScale(map, layoutName),
+                layout,
+                feature.geometry ?
+                    feature.geometry.getBounds().getCenterLonLat() :
+                    map.getCenter()
+            ).toGeometry();
+            geom.rotate(-attributes.rotation, geom.getCentroid());
+            if(feature.geometry) {
+                geom.id = feature.geometry.id;
+            }
+            feature.geometry = geom;
+            layer.drawFeature(feature);
+        }
         Ext.apply(feature.attributes, attributes);
         feature.layer.events.triggerEvent("featuremodified", {
             feature: feature
         });
-        feature.layer.drawFeature(feature);
+    },
+    
+    /** api:method[updateHandle]
+     *  :param handle: ``OpenLayers.Feature.Vector`` The handle to update
+     *  :param feature: ``OpenLayers.Feature.Vector`` The feature to align the
+     *      handle to.
+     *      
+     *  Updates the handle position to align with a feature.
+     */
+    updateHandle: function(handle, feature) {
+        if(feature.geometry) {
+            var hLoc = this.getHandleLocation(feature); 
+            var geom = new OpenLayers.Geometry.Point(hLoc.lon, hLoc.lat);
+            if(handle.geometry) {
+                geom.id = handle.geometry.id;
+            }
+            handle.geometry = geom;
+            handle.layer.drawFeature(handle);
+
+            var layout = feature.attributes.layout;
+        }
     }
     
 });

Modified: sandbox/ahocevar/playground/ux/Printing/ux/plugins/PrintLayoutField.js
===================================================================
--- sandbox/ahocevar/playground/ux/Printing/ux/plugins/PrintLayoutField.js	2009-12-03 20:59:09 UTC (rev 1547)
+++ sandbox/ahocevar/playground/ux/Printing/ux/plugins/PrintLayoutField.js	2009-12-04 00:23:43 UTC (rev 1548)
@@ -17,16 +17,17 @@
     
     init: function(target) {
         target.on({
-            "change": function(field, newValue){
-                this.setLayout(newValue);
-            },
+            "valid": this.onUpdate,
             scope: this
         });
     },
     
-    setLayout: function(layout) {
+    onUpdate: function(field) {
+        var value = field.getValue();
         Ext.each(this.layer.features, function(feature){
-            this.printProvider.updateFeature(feature, {layout: layout});
+            if(feature.attributes.layout !== undefined) {
+                this.printProvider.updateFeature(feature, {layout: value});
+            }
         }, this);
     }
 });

Modified: sandbox/ahocevar/playground/ux/Printing/ux/plugins/PrintPageAttributeField.js
===================================================================
--- sandbox/ahocevar/playground/ux/Printing/ux/plugins/PrintPageAttributeField.js	2009-12-03 20:59:09 UTC (rev 1547)
+++ sandbox/ahocevar/playground/ux/Printing/ux/plugins/PrintPageAttributeField.js	2009-12-04 00:23:43 UTC (rev 1548)
@@ -4,8 +4,12 @@
     
     printProvider: null,
     
-    feature: null,
+    target: null,
     
+    pageFeature: null,
+    
+    handle: null,
+    
     attribute: null,
     
     /** private: method[constructor]
@@ -18,20 +22,43 @@
     },
     
     init: function(target) {
+        this.target = target;
         target.on({
-            "change": function(field, newValue) {
-                this.setAttribute(newValue);
-            },
+            "valid": this.onFieldUpdate,
             scope: this
         });
+        this.pageFeature.layer.events.on({
+            "featuremodified": this.onFeatureUpdate,
+            scope: this
+        });
     },
     
-    setAttribute: function(value) {
+    onFieldUpdate: function(field) {
+        var value = field.getValue();
+        // make sure we send the *valueField* to updateFeature
+        if(field instanceof Ext.form.ComboBox && field.valueField) {
+            var index = field.store.find(field.displayField, value);
+            if(index !== -1) {
+                value = field.store.getAt(index).get(field.valueField);
+            }
+        }
         var attributes = {};
         attributes[this.attribute] = value;
-        this.printProvider.updateFeature(this.feature, attributes);
+        this.printProvider.updateFeature(this.pageFeature, attributes);
+        this.printProvider.updateHandle(this.handle, this.pageFeature);
+    },
+    
+    onFeatureUpdate: function(e) {
+        if(e.feature === this.pageFeature) {
+            var value = e.feature.attributes[this.attribute];
+            if(value && value != this.target.getValue()) {
+                this.target.suspendEvents();
+                this.target.setValue(value);
+                this.target.resumeEvents();
+            }
+        }
     }
 });
 
-/** api: ptype = gx-printscalescombo */
+/** api: ptype = gx-printpageattributefield */
 Ext.preg && Ext.preg("gx-printpageattributefield", GeoExt.ux.plugins.PrintPageAttributeField);

Modified: sandbox/ahocevar/playground/ux/Printing/ux/widgets/SimplePrint.js
===================================================================
--- sandbox/ahocevar/playground/ux/Printing/ux/widgets/SimplePrint.js	2009-12-03 20:59:09 UTC (rev 1547)
+++ sandbox/ahocevar/playground/ux/Printing/ux/widgets/SimplePrint.js	2009-12-04 00:23:43 UTC (rev 1548)
@@ -1,89 +1,177 @@
 Ext.namespace("GeoExt.ux")
 
-GeoExt.ux.SimplePrint = Ext.extend(Ext.Panel, {
+GeoExt.ux.SimplePrint = Ext.extend(Ext.form.FormPanel, {
     
-    titleText: "Title",
-    commentsText: "Comments",
     layoutText: "Layout",
     dpiText: "DPI",
     scaleText: "Scale",
     rotationText: "Rotation",
+    printText: "Print",
     
-    layout: "form",
-    
     printProvider: null,
     
     map: null,
     
+    layer: null,
+    
+    control: null,
+    
+    pageFeature: null,
+    
+    handleFeature: null,
+    
     initComponent: function() {
+        GeoExt.ux.SimplePrint.superclass.initComponent.call(this);
         if(this.map instanceof GeoExt.MapPanel) {
             this.map = this.map.map;
         }
-        
-        this.layer = new OpenLayers.Layer.Vector(null, {
-            displayInLayerSwitcher: false
-        });
-        this.layer.addFeatures(new OpenLayers.Feature.Vector(null, {}));
+                        
+        this.initLayer();
+        this.initControl();
         this.map.addLayer(this.layer);
-        
-        this.add({
-            xtype: "textfield",
-            label: this.titleText,
-            plugins: new GeoExt.ux.plugins.PrintPageAttributeField({
-                printProvider: this.printProvider,
-                attribute: "title",
-                feature: this.layer.features[0]
-            })
+        this.control.activate();
+
+        if(this.printProvider.capabilities) {
+            this.initForm();
+        } else {
+            this.printProvider.on({
+                "loadcapabilities": this.initForm,
+                scope: this
+            });
+        }
+
+        this.on({
+            "show": function() {
+                this.layer.setVisibility(true);
+                this.control.activate();
+                this.printProvider.fitPage(this.pageFeature);
+            },
+            "hide": function() {
+                this.control.deactivate();
+                this.layer.setVisibility(false);
+            }
         });
-        this.add({
-            xtype: "textfield",
-            label: this.commentsText,
-            plugins: new GeoExt.ux.plugins.PrintPageAttributeField({
-                printProvider: this.printProvider,
-                attribute: "comment",
-                feature: this.layer.features[0]
+    },
+    
+    initLayer: function() {
+        if(!this.layer) {
+            this.layer = new OpenLayers.Layer.Vector(null, {
+                displayInLayerSwitcher: false
             })
+        };
+        if(!this.pageFeature) {
+            this.pageFeature = new OpenLayers.Feature.Vector(null, {
+            layout: null});
+        }
+        this.handleFeature = new OpenLayers.Feature.Vector();
+        this.layer.addFeatures([this.pageFeature, this.handleFeature]);
+    },
+    
+    initControl: function() {
+        this.control = new OpenLayers.Control.DragFeature(this.layer, {
+            onDrag: function(feature) {
+                if(feature === this.pageFeature) {
+                    this.printProvider.updateHandle(this.handleFeature,
+                        this.pageFeature);
+                } else if(feature === this.handleFeature) {
+                    this.printProvider.updatePage(this.pageFeature,
+                        this.handleFeature);
+                }
+            }.createDelegate(this),
+            onComplete: this.printProvider.updateHandle.createDelegate(
+                this.printProvider, [this.handleFeature, this.pageFeature])
         });
-        this.add({
-            xtype: "combo",
-            label: this.layoutText,
+        this.map.addControl(this.control);
+    },
+    
+    initForm: function() {
+        var items = [{
+            xtype: this.pageLayout ? "hidden" : "combo",
+            fieldLabel: this.layoutText,
+            name: "layout",
             store: this.printProvider.layouts,
-            valueField: "value",
+            value: this.pageLayout ||
+                this.printProvider.layouts.getAt(0).get("name"),
             displayField: "name",
+            typeAhead: true,
+            mode: "local",
+            forceSelection: true,
+            triggerAction: "all",
+            selectOnFocus: true,
             plugins: new GeoExt.ux.plugins.PrintLayoutField({
                 printProvider: this.printProvider,
                 layer: this.layer
             })
-        });
-        this.add({
-            xtype: "combo",
-            label: this.dpiText,
+        }, {
+            xtype: this.dpi ? "hidden" : "combo",
+            fieldLabel: this.dpiText,
+            name: "dpi",
             store: this.printProvider.dpis,
+            value: this.dpi ||
+                this.printProvider.dpis.getAt(0).get("value"),
+            displayField: "name",
             valueField: "value",
+            typeAhead: true,
+            mode: "local",
+            forceSelection: true,
+            triggerAction: "all",
+            selectOnFocus: true,
+            valueField: "value",
             displayField: "name"
-        });
-        this.add({
+        }, {
             xtype: "combo",
-            label: this.scaleText,
+            fieldLabel: this.scaleText,
             store: this.printProvider.scales,
+            value: this.printProvider.scales.getAt(0).get("value"),
+            displayField: "name",
             valueField: "value",
-            displayField: "name",
+            typeAhead: true,
+            mode: "local",
+            forceSelection: true,
+            triggerAction: "all",
+            selectOnFocus: true,
             plugins: new GeoExt.ux.plugins.PrintPageAttributeField({
                 printProvider: this.printProvider,
                 attribute: "scale",
-                feature: this.layer.features[0]
+                pageFeature: this.pageFeature,
+                handle: this.handleFeature
             })
-        });
-        this.add({
+        }, {
             xtype: "textfield",
-            label: this.rotationText,
+            fieldLabel: this.rotationText,
+            value: 0,
+            enableKeyEvents: true,
+            validator: function(v) {
+                return !isNaN(v)
+            },
             plugins: new GeoExt.ux.plugins.PrintPageAttributeField({
                 printProvider: this.printProvider,
                 attribute: "rotation",
-                feature: this.layer.features[0]
+                pageFeature: this.pageFeature,
+                handle: this.handleFeature
             })
+        }];
+        Ext.each(items, function(item){
+            this.add(item);
+        }, this);
+
+        this.addButton({
+            text: this.printText,
+            handler: function() {
+                var options = {
+                    layer: this.layer
+                }
+                this.items.each(function(field){
+                    if(field.name) {
+                        options[field.name] = field.getValue();
+                    }
+                }, this);
+                this.printProvider.print(this.map, options);
+            },
+            scope: this
         });
+
         this.doLayout();
     }
-
+    
 });



More information about the Commits mailing list