Changeset 215


Ignore:
Timestamp:
03/10/09 14:29:03 (9 years ago)
Author:
dwins
Message:

Skeletal application for GeoExplorer project

Location:
sandbox/opengeo/drake/trunk/apps
Files:
8 deleted
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • sandbox/opengeo/drake/trunk/apps/geoexplorer/build.cfg

    r210 r215  
    2727
    2828
    29 [Drake.js]
     29[GeoExplorer.js]
    3030root=.
    3131exclude=
    3232        script/OpenLayers.js
    3333        script/GeoExt.js
    34         script/Drake.js
     34        script/GeoExplorer.js
    3535
    3636[GeoExt.js]
  • sandbox/opengeo/drake/trunk/apps/geoexplorer/index.html

    r212 r215  
    11<html>
    2 <head>
    3     <title>Drake (alpha) - A GeoExplorer</title>
    4     <link rel="stylesheet" type="text/css" href="../../externals/ext/resources/css/ext-all.css" />
    5     <link rel="stylesheet" type="text/css" href="../../externals/ext/resources/css/xtheme-gray.css" />
    6     <link rel="stylesheet" type="text/css" href="../../externals/openlayers/theme/default/style.css" />
    7     <link rel="stylesheet" type="text/css" href="../../core/theme/css/styler.css" />
    8     <link rel="stylesheet" type="text/css" href="../../core/theme/css/popup-gray.css" />
    9     <link rel="stylesheet" type="text/css" href="./theme/column-tree.css" />
    10        
    11     <script type="text/javascript" src="../../externals/ext/adapter/ext/ext-base.js"></script>
    12     <script type="text/javascript" src="../../externals/ext/ext-all-debug.js"></script>
    13     <!-- <script type="text/javascript" src="../../externals/openlayers/OpenLayers.js"></script> -->
    14     <script type="text/javascript" src="../../externals/openlayers/lib/OpenLayers.js"></script>
    15     <script>
    16     window.scriptLocation = "../../core/";
    17     </script>
    18     <script type="text/javascript" src="../../core/lib/GeoExt.js"></script>
    19     <script type="text/javascript" src="./AddLayerWindow.js"></script>
    20     <script type="text/javascript" src="./CustomFilterBuilder.js"></script>
    21     <script type="text/javascript" src="./LayerTree.js"></script>
    22     <script type="text/javascript" src="./LayerNodeUI.js"></script>
    23     <script type="text/javascript" src="./MaxFeaturesWarning.js"></script>
     2    <head>
     3        <title>GeoExplorer 0.1-pre</title>
     4        <link rel="stylesheet" type="text/css" href="../../externals/ext/resources/css/ext-all.css" />
     5        <link rel="stylesheet" type="text/css" href="../../externals/ext/resources/css/xtheme-gray.css" />
     6        <link rel="stylesheet" type="text/css" href="../../externals/openlayers/theme/default/style.css" />
     7        <link rel="stylesheet" type="text/css" href="../../core/theme/css/styler.css" />
     8        <link rel="stylesheet" type="text/css" href="../../core/theme/css/popup-gray.css" />
     9        <link rel="stylesheet" type="text/css" href="./theme/column-tree.css" />
    2410
    25     <script>
     11        <script type="text/javascript" src="../../externals/ext/adapter/ext/ext-base.js"></script>
     12        <script type="text/javascript" src="../../externals/ext/ext-all-debug.js"></script>
     13        <script type="text/javascript" src="../../externals/openlayers/lib/OpenLayers.js"></script>
     14        <script>
     15            window.scriptLocation = "../../core/";
     16        </script>
     17        <script type="text/javascript" src="../../core/lib/GeoExt.js"></script>
     18        <script>
    2619
    27     Ext.BLANK_IMAGE_URL = "../../externals/ext/resources/images/default/s.gif";
     20            Ext.BLANK_IMAGE_URL = "../../externals/ext/resources/images/default/s.gif";
    2821
    29     // These should go in a better spot.
    30     function recordize(attrs){
    31         var records = new Array();
    32             var mapping = {
    33             "double": "float",
    34             "string": "string",
    35             "long" :  "int",
    36             "MultiSurfacePropertyType": "auto"
    37         }
    38    
    39         for (var i = 0; i < attrs.length; i++){
    40             var a = attrs[i];
    41             var k = a.type.replace(/.*:/, '');
     22            GeoExplorer = {
     23                load: function() {
     24                    this.map = new OpenLayers.Map();
     25                    this.map.addLayers([
     26                    new OpenLayers.Layer.WMS("TOPP States",
     27                    '/geoserver/wms' ,{
     28                        layers: 'topp:states'
     29                        }, {
     30                        isBaseLayer: true
     31                    })
     32                    ]);
    4233
    43             if (mapping[k]){
    44                 records.push({
    45                      name: a.name, 
    46                      mapping: a.name,
    47                      type: mapping[k]
    48                 });
    49             }
    50         }
     34                    this.mapPanel = new GeoExt.MapPanel({
     35                        map: this.map,
     36                        region: 'center'
     37                    });
    5138
    52         return Ext.data.Record.create(records);
    53     }
     39                    this.layerTree = new Ext.tree.TreePanel({
     40                        region: 'west',
     41                        root: new GeoExt.tree.LayerContainer({
     42                            text: 'Map Layers',
     43                            map: this.map
     44                        })
     45                    });
    5446
    55     function columnize(attrs){
    56         var cols = new Array();
    57         for (var i = 0; i < attrs.length; i++){
    58             var a = attrs[i];
    59             if (a.type){
    60             cols.push({
    61                 id: a.name,
    62                 header: a.name,
    63                 dataIndex: a.name,
    64                 hidden: (i>11 | a.type.startsWith('gml:')),
    65                 sortable: true
    66             });
    67             } else {
    68                 console.log(a.name + " has no type");
    69             }
    70         }
    71 
    72         return cols;
    73     }
    74 
    75     GeoExt.Drake = {
    76         filterBuilder: null,
    77         grid: null,
    78        
    79         filter: null,
    80         store: null,
    81         fields: null,
    82        
    83         map: null,
    84         wfsStoreLayer: null,
    85        
    86         load: function(config) {
    87             OpenLayers.Util.extend(this, config);
    88            
    89             // Show the error window on network failures.
    90             GeoExt.RequestMgr.on("requestexception", function(request, url) {
    91                 var errorWindow = new GeoExt.ErrorWindow({
    92                     request: request,
    93                     url: url,
    94                     modal: true
    95                 });
    96                
    97                 errorWindow.show();
    98             }, this);
    99            
    100             var attributeStore = new GeoExt.data.AttributesStore({
    101                 url: this.wfsUrl + "?typename=" + this.getFullType() + "&request=describefeaturetype"
    102             });
    103    
    104             attributeStore.load({
    105                 // TODO: Rename x to something meaningful.
    106                 callback: function(x){
    107                     this.fields = [];
    108    
    109                     for (var i = 0; i < x.length; i++){
    110                         this.fields.push(x[i].data);
    111                     }
    112    
    113                     this.initFilter();
    114                     this.initFeatureStore();
    115                     this.initWMSStore();
    116                     this.initMap();
    117                    
    118                     this.initFilterBuilder();
    119                     this.initPagingBar();
    120                     this.initFeatureGrid();
    121                     this.initLayerTree();
    122                     this.initLegendPanel();
    123                    
    12447                    new Ext.Viewport({
    12548                        layout: 'border',
    126                         items: [
    127                             new Ext.Panel({
    128                                 region: "west",
    129                                 layout: "border",
    130                                 items: [
    131                                     this.filterBuilder,
    132                                     this.layerTree
    133                                 ],
    134                                 width: 370,
    135                                 collapsible: true,
    136                                 collapseMode: "mini",
    137                                 split: true
    138                             }),
    139                             this.mapPanel,
    140                             this.grid,
    141                             this.legendPanel
    142                         ]
     49                        items: [this.mapPanel, this.layerTree]
    14350                    });
    144                 },
    145                 scope: this
    146             });
    147         },
    148        
    149         initFilter: function() {
    150             this.filter = new OpenLayers.Filter.Logical({
    151                 type: OpenLayers.Filter.Logical.OR,
    152                 filters: []
    153             });
    154         },
    155        
    156         createProxy: function(params) {
    157             params = params || {};
    158             var type = params.type || this.featureType;
    159             var ns = params.namespace || 'http://www.openplans.org/topp';
    160             var prefix = params.prefix || this.featurePrefix;
     51                },
     52            };
    16153
    162             var proto = new OpenLayers.Protocol.WFS({
    163                 url: this.wfsUrl,
    164                 featureType: type,
    165                 featureNS: ns,
    166                 featurePrefix: prefix,
    167                 srsName: "EPSG:4326",
    168                 version: "1.1.0",
    169                 maxFeatures: this.maxFeatures
    170             });
    171        
    172             return new GeoExt.data.ProtocolProxy({protocol: proto});
    173         },
    174        
    175         initFeatureStore: function() {
    176             // create the data store
    177             this.featureStore = new Ext.data.Store({
    178                 proxy: this.createProxy(),
    179                 remoteSort: true,
    180                 reader: new Ext.data.JsonReader({}, [])
    181             });
    182            
    183             var showMaxFeaturesWarning = true;
    184            
    185             this.featureStore.on("load", function() {
    186                 if (showMaxFeaturesWarning && this.featureStore.getTotalCount() >= this.maxFeatures) {
    187                     var maxFeaturesWarning = new GeoExt.drake.MaxFeaturesWarning({
    188                         maxFeatures: this.maxFeatures
    189                     });
    190                    
    191                     maxFeaturesWarning.on("donotshowchange", function(newValue) {
    192                         showMaxFeaturesWarning = !newValue;
    193                     }, this);
    194                    
    195                     maxFeaturesWarning.show();
    196                 }
    197             }, this);
    198         },
    199        
    200         initWMSStore: function() {
    201             this.wmsStore = new Ext.data.GroupingStore({
    202                 url: this.wmsUrl + "?request=getcapabilities",
    203                 reader: new GeoExt.data.WMSCapabilitiesReader(),
    204                 sortInfo: {field: 'prefix'},
    205                 groupField: 'prefix'
    206             });
    207         },
    208        
    209         initFilterBuilder: function() {
    210             this.filterBuilder = new GeoExt.drake.CustomFilterBuilder({
    211                 title: "Filter Builder",
    212                 region: "south",
    213                 height: 175,
    214                 autoScroll: true,
    215                 filter: this.filter.clone(),
    216                 attributes: new GeoExt.data.AttributesStore({
    217                     url: this.getWFSLayerURL(this.getFullType()),
    218                     ignore: {name: "the_geom"}
    219                 }),
    220                 addToToolbar: ["->", new Ext.form.Checkbox({
    221                     boxLabel: "Use Filter",
    222                     enableToggle: true,
    223                     handler: function(checkbox, checked) {
    224                         if (checked){
    225                             this.featureStore.proxy.setOGCFilter(this.filterBuilder.getFilter());
    226                             this.filterBuilder.on("change", this.updateQueryFilter, this);
    227                         } else {
    228                             this.featureStore.proxy.setOGCFilter(null);
    229                             this.filterBuilder.un("change", this.updateQueryFilter, this);
    230                         }
    231                         this.reloadFeatureStore();
    232                     },
    233                     scope: this
    234                 })]
    235             });
    236         },
    237        
    238         initPagingBar: function() {
    239             this.pagingBar = new Ext.PagingToolbar({
    240                 pageSize: 7,
    241                 store: this.featureStore,
    242                 displayInfo: true,
    243                 displayMsg: 'Displaying features {0} - {1} of {2}',
    244                 emptyMsg: 'No features to display'
    245             });
    246         },
    247        
    248         initMap: function() {
    249             this.map = new OpenLayers.Map({
    250                 theme: null,
    251                 controls: [],
    252                 units: "m",
    253                 projection: new OpenLayers.Projection("EPSG:4326"),
    254                 // maxExtent: new OpenLayers.Bounds(-139.53227612499998,20.816194750000008,-59.55180737499998,55.44510100000001)
    255                 maxExtent: new OpenLayers.Bounds(-180,-90,180,90)
    256             });
    257                  
    258             this.wfsStoreLayer = new GeoExt.layer.Vector("Vector Layer", {
    259                     store: this.featureStore,
    260                     displayInLayerSwitcher: false
    261                 }
    262             );
    263            
    264             var baseLayer = new OpenLayers.Layer.WMS(
    265                 "OpenStreetMap",
    266                 "http://demo.opengeo.org/geoserver_openstreetmap/gwc/service/wms",
    267                 {layers: 'openstreetmap', format:'image/png'}, {isBaseLayer: true}
    268             );
    269    
    270             var vmap0 = new OpenLayers.Layer.WMS(
    271                 "Metacarta Vmap0",
    272                 "http://labs.metacarta.com/wms/vmap0",
    273                 {layers: 'basic'}, {isBaseLayer: true}
    274             );
    275    
    276    
    277             var countries = new OpenLayers.Layer.WMS(
    278                 "Political Boundaries",
    279                 this.wmsUrl,
    280                 {layers: 'topp:countries'}, {isBaseLayer: true}
    281             );
    282          
    283             // Add some layers with a dummy base layer.
    284             this.map.addLayers([
    285                 baseLayer,
    286                 vmap0,
    287                 countries,
    288                 this.wfsStoreLayer
    289             ]);
    290            
    291             this.map.addControl(new OpenLayers.Control.Navigation());
    292             this.map.addControl(new OpenLayers.Control.PanZoomBar());
    293            
    294             this.mapPanel = new GeoExt.MapPanel({
    295                 region: "center",
    296                 map: this.map,
    297                 zoom: 4,
    298                 center: new OpenLayers.LonLat(-99.54204174999998,38.13064787500001)
    299             });
    300         },
    301        
    302         initFeatureGrid: function() {
    303 
    304             this.grid = new Ext.grid.GridPanel({
    305                 title: "Feature Query Results",
    306                 stripeRows: true,
    307                 height:230,
    308                 region: "south",
    309                 collapsible: true,
    310                 collapseMode: "mini",
    311                 loadMask: {
    312                     msg: "Loading features...",
    313                     store: this.featureStore
    314                 },
    315                 columns: [],
    316                 store: this.featureStore,
    317                 selModel: new GeoExt.grid.FeatureSelectionModel({
    318                         layer: this.wfsStoreLayer
    319                 }),
    320                 bbar: this.pagingBar
    321             });
    322            
    323             this.grid.on("rowdblclick", function(grid, index, evt) {
    324                 var record = grid.getSelectionModel().getSelected();
    325                
    326                 if (record) {
    327                     var bounds = record.data.feature.geometry.getBounds();
    328                     this.map.zoomToExtent(bounds);
    329                 }
    330             }, this);
    331            
    332    
    333             ///////////// POPUP STUFF
    334              
    335             this.grid.getSelectionModel().on("rowselect", function (model, row, record){
    336                 var feature = record.data.feature;
    337    
    338                 var content = "<p> You selected " + feature.fid + "! I am truly impressed! </p>";   
    339 
    340                 feature.popup = new GeoExt.popup.Popup({
    341                     title: feature.fid,
    342                     feature: feature,
    343                     width: 235,
    344                     height: 70,
    345                     html: content,
    346                     collapsible: true,
    347                     collapsed: true,
    348                     expandOnShow: false
    349                 });
    350 
    351                 var popup = feature.popup;
    352                 this.grid.store.on("load", function(store, records, options){
    353                     var record;
    354                     for(var i = 0; i < records.length; i++){
    355                         if(records[i].data.feature == feature){
    356                             return;
    357                         }
    358                     }
    359                     if(popup.anc){
    360                         popup.close();
    361                     }
    362                 });
    363    
    364                 feature.popup.addToMapPanel(this.mapPanel);
    365             }, this);
    366    
    367             this.grid.getSelectionModel().on("rowdeselect", function(model, row, record){
    368                 var feature = record.data.feature;
    369                 if(feature.popup.anc){
    370                     feature.popup.close();
    371                 }
     54            Ext.onReady(function() {
     55                GeoExplorer.load();
    37256            });
    37357
    374         },
    375        
    376         initLayerTree: function() {
    377             var addLayerButton = new Ext.Button({
    378                 text: "Add Layer...",
    379                 disabled: true,
    380                 handler: function() {
    381                     var win = new GeoExt.drake.AddLayerWindow({
    382                         capsStore: this.wmsStore
    383                     });
    384                    
    385                     win.on("layerschosen", function(layers) {
    386                        
    387                         var layer;
    388                         for (var index = 0; index < layers.length; index++) {
    389                             var layerRecord = layers[index];
    390                             var name = layerRecord.data.name;
    391                             var tilesOrigin = layerRecord.data.llbbox[0] + "," + layerRecord.data.llbbox[1];
    392                            
    393                             layer = new OpenLayers.Layer.WMS(name, this.wmsUrl, {
    394                                 layers: name,
    395                                 format: "image/png",
    396                                 transparent: "true",
    397                                 tiled: true,
    398                                 tilesOrigin: tilesOrigin
    399                             }, {
    400                                 isBaselayer: false,
    401                                 maxExtent: OpenLayers.Bounds.fromArray(layerRecord.data.llbbox)
    402                             });
    403 
    404                             layer.drakestyles = layerRecord.data.styles;
    405                            
    406                             var found = false;
    407                             for (var layersIndex = 0; layersIndex < this.map.layers.length; layersIndex++) {
    408                                 if (this.map.layers[layersIndex] instanceof OpenLayers.Layer.WMS) {
    409                                     if (layer.params.LAYERS == this.map.layers[layersIndex].params.LAYERS) {
    410                                         found = true;
    411                                         break;
    412                                     }
    413                                 }
    414                             }
    415                            
    416                             if (!found) {
    417                                 this.map.addLayer(layer);
    418                             }
    419                         }
    420                     }, this);
    421                    
    422                     win.show();
    423                 },
    424                 scope: this
    425             });
    426            
    427            
    428             var root = new Ext.tree.TreeNode({});
    429            
    430             var baseLayerContainer = new GeoExt.tree.BaseLayerContainer({
    431                 map: this.map
    432             });
    433            
    434             var wfsStore = new Ext.data.Store({
    435                 reader: new GeoExt.data.WFSCapabilitiesReader(),
    436                 url: this.wfsUrl + "?request=GetCapabilities"
    437             });
    438            
    439             // TODO: We should probably have some UI that shows the layer tree is loading,
    440             // as the overlayContainer will not be added to the layerTree until the
    441             // wfsStore's request returns. This is not Hugely Important Right Now, but
    442             // experience tells me that for some user, at some point, this request
    443             // is gonna hang.
    444             wfsStore.load({
    445                 callback: function(response) {
    446                     var overlayContainer = new GeoExt.tree.OverlayLayerContainer({
    447                         map: this.map
    448                     });
    449                    
    450                     overlayContainer.on("customizeconfig", function(config, layer) {
    451                         config.uiProvider = GeoExt.drake.LayerNodeUI;
    452                         config.queryable = wfsStore.find("name", layer.params.LAYERS) >= 0;
    453                     });
    454                    
    455                     root.appendChild(overlayContainer);
    456                    
    457                     // Don't allow them to click the Add Layer button until we
    458                     // have all the data we need. (i.e., we have it all now,
    459                     // so enable the button).
    460                     addLayerButton.setDisabled(false);
    461                 }
    462             })
    463            
    464             root.appendChild(baseLayerContainer);
    465            
    466             this.layerTree = new GeoExt.tree.LayerTree({
    467                 border: false,
    468                 split: true,
    469                 rootVisible: false,
    470                 title: "Layers",
    471                 region: "center",
    472                 autoScroll: true,
    473                 root: root,
    474                 bbar: [
    475                     addLayerButton,
    476                     new Ext.Button({
    477                         text: "Remove selected",
    478                         handler: function() {
    479                             var nodes = layerTree.getSelectionModel().getSelectedNodes();
    480                             for (var i = 0; i < nodes.length; i++){
    481                                 var layerName = nodes[i].text;
    482                                 for (var j = 0; j < map.layers.length; j++) {
    483                                     if (map.layers[j] instanceof OpenLayers.Layer.WMS) {
    484                                         if (layerName == map.layers[j].params.LAYERS) {
    485                                             map.layers[j].destroy();
    486                                             break;
    487                                         }                                 }
    488                                     }
    489                                 }
    490                             }
    491                         })
    492                 ]
    493             });
    494    
    495             this.layerTree.on("contextmenu", function(node, e){
    496                 if (node.layer){
    497                     var menuConfig = [{
    498                         id: "zoomtobounds",
    499                         text: "Zoom to layer bounds",
    500                         handler: function(evt){
    501                                 this.map.zoomToExtent(node.layer.maxExtent);
    502                         },
    503                         scope: this
    504                     }];
    505 
    506                     if (node.layer.drakestyles && node.layer.drakestyles.length > 1){
    507                         for (var i = 0; i < node.layer.drakestyles.length; i++){
    508                             var style = node.layer.drakestyles[i];
    509                             menuConfig.push({id: style.name,
    510                                 text: "Render by \"" + style.title + '"',
    511                                 handler: function(style){
    512                                     return function(evt){
    513                                         node.layer.params.STYLES = style.name;
    514                                         node.layer.redraw();
    515                                     };
    516                                 }(style),
    517                                 scope: this
    518                             });
    519                         }
    520                     }
    521 
    522                     var menu = new Ext.menu.Menu(menuConfig);
    523                     menu.showAt(e.getPoint());
    524                 }
    525             }, this); 
    526 
    527             this.layerTree.on("layeractivated", this.activateLayer, this);
    528         },
    529        
    530         addLayerHandler: function() {
    531            
    532         },
    533        
    534         initLegendPanel: function() {
    535             this.legendPanel = new GeoExt.LegendPanel({
    536                 map: this.map,
    537                 region: "east",
    538                 title: "Legend",
    539                 width: 200,
    540                 bodyStyle: "padding: 5px",
    541                 collapsible: true,
    542                 autoScroll: true
    543             });
    544         },
    545        
    546         getFullType: function() {
    547             return this.featurePrefix + ":" + this.featureType;
    548         },
    549 
    550         getWFSLayerURL: function(type) {
    551             return this.wfsUrl + "?request=DescribeFeatureType&typename=" + type;
    552         },
    553 
    554         activateLayer: function(layer) {
    555             this.filterBuilder.attributes = new GeoExt.data.AttributesStore({
    556                 url: this.getWFSLayerURL(layer.name),
    557                 ignore: {name: "the_geom"}
    558             });
    559             this.filterBuilder.setFilter(null);
    560 
    561             var typename = layer.params.LAYERS;
    562                         // update fields
    563             var attributeStore = new GeoExt.data.AttributesStore({
    564                 url: this.wfsUrl + "?typename=" + typename + "&request=describefeaturetype"
    565             });
    566    
    567             attributeStore.load({
    568                 // TODO: Rename x to something meaningful.
    569                 callback: function(x){
    570                     this.fields = [];
    571    
    572                     for (var i = 0; i < x.length; i++){
    573                         this.fields.push(x[i].data);
    574                     }
    575 
    576                     this.finishActivating(attributeStore.reader.namespace, typename);
    577                 },
    578                 scope: this
    579             });
    580         },
    581 
    582         finishActivating: function(namespace, typename) {
    583             var parts = typename.split(':');
    584             this.featurePrefix = parts[0];
    585             this.featureType   = parts[1];
    586 
    587             this.featureStore.proxy = this.createProxy({prefix: parts[0], type: parts[1], namespace: namespace});
    588             this.featureStore.reader = new GeoExt.data.FeatureReader({}, recordize(this.fields));
    589  
    590             this.grid.setTitle(typename + " - " + namespace);
    591             this.grid.colModel.setConfig(columnize(this.fields));
    592 
    593             this.reloadFeatureStore();
    594         },
    595 
    596         updateQueryFilter: function(builder){
    597             this.featureStore.proxy.setOGCFilter(builder.getFilter());
    598             this.reloadFeatureStore();
    599         },
    600        
    601         reloadFeatureStore: function() {
    602             this.featureStore.load({
    603                 params: {
    604                     start: 0,
    605                     limit: this.featuresPerPage
    606                 }
    607             });
    608         }
    609     };
    610 
    611     Ext.onReady(function() {
    612         GeoExt.Drake.load({
    613             featurePrefix: "topp",
    614             featureType: "states",
    615            
    616             geoserverUrl: "/geoserver",
    617             wmsUrl: "/geoserver/wms",
    618             wfsUrl: "/geoserver/wfs",
    619            
    620             maxFeatures: 300,
    621             featuresPerPage: 7
    622         });
    623     });
    624 
    625     </script>
    626 </head>
    627 <body>
    628 </body>
     58        </script>
     59    </head>
     60    <body>
     61    </body>
    62962</html>
Note: See TracChangeset for help on using the changeset viewer.