Thursday, 20 March 2014

Bugfix release GeoExt v2.0.1 is available

We are pleased to announce GeoExt 2.0.1, which is the first bugfix release of the GeoExt 2-series.

This release only fixes minor issues with 2.0.0. This is what is included:

  • Fix GeoExt.Version #201
  • Use theme-switcher in examples #202
  • Made GeoExt.LayerModel extendable #203
  • Refactor sliders #204 & #205
  • Testsuite enhancements #211 & #214
  • various minor bugfixes

All users of GeoExt 2 are encouraged to update to this version. Updating should be no problem and should not break your applications built on top of GeoExt 2.

Thanks to everyone who was involved in building this version.

Monday, 28 October 2013

extending GeoExt.data.LayerModel with extra fields

In Ext 4 the data package has changed quite a bit. What was called a Record in Ext 3, is now called a Model. Also, adding extra fields to an existing model requires a different approach.

In GeoExt 1 we were able to do things like:

  // create a layer record for this layer
  var Record = GeoExt.data.LayerRecord.create([
    {name: "name", type: "string"},
    {name: "source", type: "string"},
    {name: "group", type: "string"},
    {name: "fixed", type: "boolean"},
    {name: "selected", type: "boolean"},
    {name: "type", type: "string"},
    {name: "args"}

  ]);

  var data = {
    layer: layer,
    title: layer.name,
    name: config.name || layer.name,
    source: config.source,
    group: config.group,
    fixed: ("fixed" in config) ? config.fixed : false,
    selected: ("selected" in config) ? config.selected : false,
    type: config.type,
    args: config.args,
    properties: ("properties" in config) ? config.properties : undefined
  };
  record = new Record(data, layer.id);

However in GeoExt 2 this requires a different approach, and I ran into an issue in GeoExt 2 whilst doing this see this PR

Basically static properties and methods are not automatically inherited in Ext 4, we need to explicitly use inheritableStatics for them to get inherited. Also we need to make sure we don't use instance properties in the static method itself, but only static methods.

In GeoExt 2 all extra properties are read through the metadata object which is present on OpenLayers Layer instances. So we need to follow this approach for our custom fields as well, which leads to:

Ext.define('gxp.data.OLLayerModel',{
  extend: 'GeoExt.data.LayerModel',
  fields: [
     {name: "name", type: "string", mapping: 'metadata.name'},
     {name: "source", type: "string", mapping: 'metadata.source'},
     {name: "group", type: "string", mapping: 'metadata.group'},
     {name: "fixed", type: "boolean", mapping: 'metadata.fixed'},
     {name: "selected", type: "boolean", mapping: 'metadata.selected'},
     {name: "type", type: "string", mapping: 'metadata.type'}, 
     {name: "args", type: "array", mapping: 'metadata.args'},
     {name: "properties", type: "string", mapping: 'metadata.properties'}
  ]
});

Ext.apply(layer.metadata, {
  name: config.name || layer.name,
  source: config.source,
  group: config.group,
  fixed: ("fixed" in config) ? config.fixed : false,
  selected: ("selected" in config) ? config.selected : false,
  type: config.type,
  args: config.args,
  properties: ("properties" in config) ? config.properties : undefined
});
record = gxp.data.OLLayerModel.createFromLayer(layer);

Friday, 25 October 2013

Finally: GeoExt 2.0.0 released

Two weeks after the first release candidate, we are happy and proud to announce the release of GeoExt 2.0.0!

Download it at https://github.com/geoext/geoext2/releases/tag/v2.0.0

GeoExt 2.0.0 is the first official GeoExt version that is built atop of OpenLayers 2.13.1 and ExtJS 4.2.1.

Read more about this release over at github, download GeoExt 2.0.0, and use it in your OpenLayers 2.13.1 and Ext JS 4.2.1 powered webpage. Do so by telling the autoloading-mechanism of Ext about GeoExt:

Ext.Loader.setConfig({
  enabled: true,
  paths: {
    GeoExt: "path/to/geoext2/src",
    Ext: "path/to/extjs/src"
  }
});


We are looking forward to your feedback on this release.


Tuesday, 15 October 2013

Announcement: GeoExt 2.0.0-rc.1 released

The GeoExt community is proud to announce the first release candidate of GeoExt 2.0.0.

Download it at https://github.com/geoext/geoext2/releases/tag/2.0.0-rc.1

GeoExt 2.0.0-rc.1 is the first official GeoExt version that is built atop of OpenLayers 2.13.1 and ExtJS 4.2.1. It has been in the making for quite a while, but most of the code comes from a code sprint in Bonn, Germany, that happened last year.

The newest major version of GeoExt wants to provide mostly the same API you know and love from the 1.x-series. It comes with support for the autoloading-mechanism of ExtJS, support for the single-file build tool of Sencha and with an exhaustive documentation that is built using the same tools as ExtJS. There are two versions of the API-docs: one has only the GeoExt-classes, while the other also has the basic Ext-classes, from which properties and methods might be inherited.

This release wouldn't have been possible without the sponsors of the above mentioned sprint. Also we want to thank the companies behind the contributors of GeoExt for supporting GeoExt development in numerous ways.

We invite you to test the release candidate! To do so, download GeoExt 2.0.0-rc.1 from (see above) and use it in your OpenLayers 2.13.1 and Ext JS 4.2.1 powered webpage by telling the autoloading-mechanism of Ext about GeoExt:

    Ext.Loader.setConfig({
        enabled: true,
        paths: {
            GeoExt: "path/to/geoext2/src",
            Ext: "path/to/extjs/src"
        }
    });

Have a look at the examples and additional information listed at the GeoExt 2 website over at github: http://geoext.github.io/geoext2/

We are looking forward to your feedback on this release.

[Edited 2013-10-16: Removed typos]

Thursday, 18 October 2012

OpenLayers 3: Invest in the web mapping future !

OpenLayers Community has initiated a call for funding in order to develop a brand new release based on the latest technogies: OpenLayers 3. If this becomes a reality, than GeoExt will also benefit of these new possibilities and would allow to develop awesome applications.
Please get in touch at ol3-funding@googlegroups.com if you’re interesting in being involved.


Saturday, 12 May 2012

GeoExt 2 - more technical details

This blog post provides more details on GeoExt 2 and Ext JS 4, focusing on technical aspects

So GeoExt 2 is a port of GeoExt 1 to Ext JS 4. The GeoExt 2 code sprint was really about porting the existing code base to Ext JS 4, redesigning, and rewriting code, only when simple adaptations were not possible.

GeoExt 2 works with Ext JS 4 only. Ext JS 3 and lower aren't supported, and won't be, obviously.

Note also that GeoExt 2 doesn't work with Sencha Touch. Sencha Touch and Ext JS 4 have similarities but their APIs are too different to write code that works with both libs. We actually did attempt to make map panel work with both Ext JS 4 and Sencha Touch, but failed.

The class system

The class system of Ext JS 4 is quite different from that of Ext JS 3. Ext JS 3 had no specific mechanism for defining classes, and had Ext.extend to define child classes. With Ext JS 4 classes are defined using Ext.define. Defining a parent class is done as follows:

Ext.define('P', {
    // prototype object
});

Defining a child class is done as follows:

Ext.define('C', {
    extend: 'P',
    // prototype object
});

In the above examples the P and C constructors are added to the window namespace. To create a class without adding a reference to it in the global namespace Ext.Class can be used. Ext.define actually uses Ext.Class internally, and most of the time you should not need to use Ext.Class.

So porting GeoExt to Ext JS 4 has required using Ext.define for every class definition – the easy part of the porting work really.

Another major change in Ext JS 4 is the way classes should be instantiated. Although using the new keyword still works (thank god!) using Ext.create is recommended. For example:

    var c = Ext.create('C');

Using Ext.create Ext JS will actually load the script containing the class if the class is not defined yet. This is called "synchronous loading" in the Ext JS 4 jargon, which means "load the class at the time it is actually needed".

The autoloader also supports "asynchronous loading". When relying on asynchronous loading, scripts are loaded earlier, in fact as soon as Ext.require is called or when classes with specific requirements (defined with "requires" in the class) are defined. Synchronous loading works with XHR while asynchronous loading works by dynamically adding script tags to the page.

The data components

The data types/components in Ext JS 4 work differently from Ext JS 3. Ext JS 4 has introduced the notion of “model”. A model, which is a class, defines a data schema. For example:

Ext.define('my.Model', {
    extend: 'Ext.data.Model',
    fields: [{
        name: 'text', type: 'string'
    }, {
        name: 'code', type: 'int'
    }]
});

This defines a data model with two fields/columns: "text" and "code". The defined model class can then be used in a store. For example:

var store = Ext.create('Ext.data.Store', {
    model: 'my.Model'
});

GeoExt 2 defines its own data models. To name a few: LayerModel, WmsCapabilitiesLayerModel, WmsDescribeLayerModel to name a few.

GeoExt 2 also defines preconfigured stores. For example GeoExt 2 includes WmsDescribeLayerStore which is preconfigured with WmsDescribeLayerModel.

As GeoExt 1, the goal of GeoExt 2's data components is to ease working with geo data and metadata in Ext JS applications. But we had to rethink and redesign things in GeoExt 2, to adapt to Ext JS 4's new architecture and concepts.

The tree components

(paragraph contributed by Andreas Hocevar) Trees have seen a complete overhaul in Ext JS 4. Instead of loaders, every node in a tree now has a store for its child nodes. While the Ext JS 4 tree is more flexible than the Ext JS 3 one when it comes to columns (the tree is a grid), there are less extension points for customizations on the node level. And GeoExt 1 did a lot of customizations on the node level. But despite these difficulties, we were able to come up with a nice API for configuring trees. Let's have a look at a tree configuration for including a WMS GetLegendGraphic image for each layer in GeoExt 1:

// custom layer node UI class
var LayerNodeUI = Ext.extend(
    GeoExt.tree.LayerNodeUI,
    new GeoExt.tree.TreeNodeUIEventMixin()
);
var tree = new Ext.tree.TreePanel({
    // apply the tree node component plugin to layer nodes
    plugins: [{
        ptype: "gx_treenodecomponent"
    }],
    loader: {
        applyLoader: false,
        uiProviders: {
            custom_ui: LayerNodeUI
        }
    },
    root: {
        nodeType: "gx_layercontainer",
        loader: {
            baseAttrs: {
                uiProvider: "custom_ui"
            },
            createNode: function(attr) {
                // add a WMS legend to each node created
                attr.component = {
                    xtype: "gx_wmslegend",
                    layerRecord: mapPanel.layers.getByLayer(attr.layer),
                    showTitle: false,
                    // custom class for css positioning
                    // see tree-legend.html
                    cls: "legend"
                };
                return GeoExt.tree.LayerLoader.prototype.createNode.call
                           (this, attr);
            }
        }
    },
    rootVisible: false,
    lines: false
});

Obviously the configuration of a custom TreeNodeUI to get additional events on the tree, which are needed by the gx_treenodecomponent plugin is a bit cumbersome. With GeoExt 2, the same tree can be achieved with a much nicer configuration:

var store = Ext.create('Ext.data.TreeStore', {
    model: 'GeoExt.data.LayerTreeModel',
    root: {
        plugins: [{
            ptype: "gx_layercontainer",
            loader: {
                createNode: function(attr) {
                    // add a WMS legend to each node created
                    attr.component = {
                        xtype: "gx_wmslegend",
                        layerRecord: mapPanel.layers.getByLayer(
                                          attr.layer),
                        showTitle: false,
                        // custom class for css positioning
                        // see tree-legend.html
                        cls: "legend"
                    };
                    return GeoExt.tree.LayerLoader.prototype.createNode.call
                              (this, attr);
                }
            }
        }]
    }
});
var tree = new GeoExt.tree.Panel({
    store: store,
    rootVisible: false,
    lines: false
});

The node (here: the root node) can be configured with plugins. Note that this is not an Ext JS 4 extension point, but one that we created in GeoExt 2. As long as your tree is a GeoExt.tree.TreePanel instead of an Ext.tree.TreePanel, and its store is configured with a GeoExt.tree.LayerTreeModel instead of the default model, there are no special configuration options needed to make the already built-in component rendering available.

Instead of having this built into our default tree view (the one the GeoExt.tree.TreePanel is configured with), we could also move it into a plugin before the final release. This decision depends on how much code the other plugins (like the ActionPlugin and RadioButtonPlugin) require, and our architecture allows us to create an extension point here any time.

Friday, 11 May 2012

GeoExt2 Sprint Results

Today was the final day of the sprint, and we are proud to announce that GeoExt2 is ready for an early alpha release. Most of the key features that our sponsors were interested in could be ported from GeoExt1. Examples matching previous examples are available for most of the ported components, so it should be easy for application developers to port their applications to Ext4/GeoExt2.

To continue our tradition of giving credit to the developers who put an incredible amount of energy into making GeoExt2 a reality, here is the list of today's achievements:

  • Alexandre finished a MVC demo application that shows the power of Ext4 and GeoExt2, and fixed many tests and examples.
  • Andreas and Julien were able to finish big portions of the tree functionality, just in time before the end of the sprint, and just before going crazy over the complexity of the internals of Ext4. In addition to the synchronization between map and tree, all the loaders (except for the LayerParamsLoader) and the TreeNodeComponent plugin were implemented. Because the Ext4 architecture of trees is too much different from Ext3, a new (and nicer) API for building tree configurations was introduced.
  • Bart and Matt and Frédéric wrapped up their work on data components - even the not so famous ones like the SymbolizerColumn or the GeocoderCombo. A nice improvement, which also received contributions from other sprinters, is the common OwsStore base class for OGC data sources. Bart also brought basic i18n to GeoExt2.
  • Christian, Marc and Johannes made all print components work with Ext4. They also made huge improvements to many of the examples.
  • Éric gave the new MapPanel a big overhaul, so it is more lightweight and feature complete than the initial port. Together with François, he finished the AttributeReader and all components from the form namespace. They also took care of dependency management and made improvements to the build story.
  • Stéphane did a great job reviewing many of the pull requests that had piled up during the week, and helped to keep the pile of open tickets small. He also contributed to the MVC demo application mentioned above.

Next Steps

Over the weekend, we will be trying to brush up the API documentation and create an official alpha release. At this point, some components still need unit tests, and there may be some loose ends that are best encountered by using GeoExt2 in real life applications.

This means: we invite everyone to test the upcoming alpha release, or get the latest code from github. Bug reports, and - more than ever - code contributions and bugfix pull requests on github are welcome. Getting out a final 2.0 release soon is a goal that can only be reached with help from the community. For talented developers, a reward for repeated quality code contributions is the nomination for GeoExt2 core committer status.

Thanks again to all our sponsors, and to terrestris for the organization of the sprint and the perfect venue. And of course to all my fellow sprinters for all the good and hard work.

Happy coding, and may the odds be ever in your favor!