Skip to content

Commit

Permalink
Merge pull request geoext#147 from geoext/stylereader
Browse files Browse the repository at this point in the history
More robust style store
  • Loading branch information
Matt Priour committed May 18, 2012
2 parents 24ef376 + bf294c7 commit e463a98
Show file tree
Hide file tree
Showing 8 changed files with 225 additions and 58 deletions.
1 change: 0 additions & 1 deletion examples/stylegrid/style-grid.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
<head>
<title>GeoExt StyleReader</title>
<link rel="stylesheet" type="text/css" href="http://cdn.sencha.io/ext-4.1.0-gpl/resources/css/ext-all.css">
<link rel="stylesheet" type="text/css" href="../../resources/css/tree.css">
<script type="text/javascript" charset="utf-8" src="http://cdn.sencha.io/ext-4.1.0-gpl/ext-dev.js"></script>

<!-- You should definitely consider using a custom single-file version of OpenLayers -->
Expand Down
64 changes: 36 additions & 28 deletions examples/stylegrid/style-grid.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,41 +25,48 @@ var vectorGrid, rasterGrid;

Ext.require([
'GeoExt.data.StyleStore',
//'GeoExt.grid.column.Symbolizer',
'GeoExt.grid.column.Symbolizer',
'Ext.grid.GridPanel',
'Ext.grid.plugin.RowEditing'
'Ext.grid.plugin.RowEditing',
'Ext.grid.plugin.DragDrop'
]);

Ext.application({
name: 'Feature Grid - GeoExt2',
launch: function() {

var columns = [
//{dataIndex: "symbolizers", width: 26, xtype: "gx_symbolizercolumn"},
{dataIndex: "symbolizers", width: 30, xtype: "gx_symbolizercolumn"},
{header: "Label", dataIndex: "label", editor: {xtype: "textfield"}},
{header: "Filter", dataIndex: "filter", editor: {xtype: "textfield"}}
{header: "Filter", dataIndex: "filter", editor: {xtype: "textfield"},flex: 1}
];


vectorGrid = Ext.create('Ext.grid.GridPanel',{
width: 220,
height: 115,
height: 200,
columns: columns.concat(),
viewConfig: {autoFill: true},
plugins: [
Ext.create('Ext.grid.plugin.RowEditing', {
clicksToEdit: 1
})
],
store: Ext.create('GeoExt.data.StyleStore',
{data: vectorStyle }
),
renderTo: "vectorgrid"
/*enableDragDrop: true,
ddGroup: "vgrid",
viewConfig: {
autoFill: true,
plugins: {
ptype: 'gridviewdragdrop',
dragText: 'Drag and drop to reorganize'
}
},
plugins: {
ptype: 'rowediting',
clicksToEdit: 1
},
store: Ext.create('GeoExt.data.StyleStore', {
data: vectorStyle,
storeId: 'vectorstyle'
}),
renderTo: "vectorgrid",
enableDragDrop: true,
//ddGroup: "vgrid",
listeners: {
//afteredit: function(e) {e.grid.store.commitChanges();},
render: function makeDD(grid) {
edit: function(g,e,opt) {e.record.commit();},
/* render: function makeDD(grid) {
store = grid.store;
new Ext.dd.DropTarget(grid.getView().mainBody, {
ddGroup : "vgrid",
Expand All @@ -77,9 +84,9 @@ Ext.application({
}
}
});
},
},*/
scope: this
}*/
}
});
rasterGrid = Ext.create('Ext.grid.GridPanel',{
width: 220,
Expand All @@ -92,13 +99,14 @@ Ext.application({
clicksToEdit: 1
})
],
store: Ext.create('GeoExt.data.StyleStore',
{data: rasterStyle.rules[0].symbolizers[0]}
),
renderTo: "rastergrid"//,
//listeners: {
// afteredit: function(e) {e.grid.store.commitChanges();}
//}
store: Ext.create('GeoExt.data.StyleStore', {
data: rasterStyle.rules[0].symbolizers[0],
storeId: 'rasterstyle'
}),
renderTo: "rastergrid",
listeners: {
edit: function(g,e,opt) {e.record.commit();}
}
});
}
});
10 changes: 9 additions & 1 deletion src/GeoExt/data/RasterStyleModel.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Ext.define('GeoExt.data.RasterStyleModel',{
stroke: false
};
}, defaultValue: null},
{name: "filter", mapping: "quantity", type: "float"},
{name: "filter", mapping: "quantity", type: "float", sortType: 'asFloat', sortDir: 'ASC'},
{name: "label", mapping: function(v) {
// fill label with quantity if empty
return v.label || v.quantity;
Expand All @@ -42,5 +42,13 @@ Ext.define('GeoExt.data.RasterStyleModel',{
type: 'json',
root: 'colorMap'
}
},
listeners:{
idchanged:function(rec){
for(var i=0;i<rec.stores.length;i++){
var store = rec.stores[i];
store.sort();
}
}
}
});
10 changes: 5 additions & 5 deletions src/GeoExt/data/StyleStore.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,16 +47,16 @@ Ext.define('GeoExt.data.StyleStore', {
'GeoExt.data.RasterStyleModel'
],
alias: 'store.gx_style',
sorters: [{
property: 'filter',
direction: 'ASC'
}],

constructor: function(config){
config = Ext.apply({}, config);
if(config.data && !config.model){
if (config.data instanceof OpenLayers.Symbolizer.Raster) {
config.model = 'GeoExt.data.RasterStyleModel';
config.sorters = [{
property: 'filter',
direction: 'ASC',
root: 'data'
}];
} else {
config.model = 'GeoExt.data.VectorStyleModel';
}
Expand Down
63 changes: 41 additions & 22 deletions src/GeoExt/data/VectorStyleModel.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
/*
* Copyright (c) 2008-2012 The Open Source Geospatial Foundation
*
* Published under the BSD license.
* See https://github.com/geoext/geoext2/blob/master/license.txt for the full text
* of the license.
*/
* Copyright (c) 2008-2012 The Open Source Geospatial Foundation
*
* Published under the BSD license.
* See https://github.com/geoext/geoext2/blob/master/license.txt for the full text
* of the license.
*/

/*
* @include OpenLayers/Format/CQL.js
*/
* @include OpenLayers/Format/CQL.js
*/

/**
* @class GeoExt.data.VectorStyleModel
Expand All @@ -20,26 +20,45 @@
Ext.define('GeoExt.data.VectorStyleModel', {
extend : 'Ext.data.Model',
requires : ['Ext.data.JsonReader'],
fields : [
{name: "elseFilter", defaultValue: null},
{name: "symbolizers", defaultValue: null},
{name : "label", mapping : "title" },
{name: "filter", convertor: function(filter){
if (typeof filter === "string") {
fields : [{
name : "elseFilter",
defaultValue : null
}, {
name : "label",
mapping : "title",
type : 'string'
}, "name", "description", "minScaleDenominator", "maxScaleDenominator", {
name : "symbolizers",
convert : function(symbolizers, rec) {
//symbolizers should be an array of OpenLayers.Symbolizer objects
symbolizers = ( symbolizers instanceof Array) ? symbolizers : [symbolizers];
for(var i = 0; i < symbolizers.length; i++) {
var symbolizer = symbolizers[i];
//due to the way that the initial data provided to a store is processed,
//the instanceof test no longer works and we need to clone the symbolizer
//for it to be recognized as a symbolizer class again
if(!( symbolizer instanceof OpenLayers.Symbolizer) && symbolizer.CLASS_NAME && symbolizer.clone) {
symbolizers[i] = symbolizer.clone();
}
}
return symbolizers;
},
defaultValue : null
}, {
name : "filter",
convert : function(filter) {
if( typeof filter === "string") {
filter = filter ? OpenLayers.Format.CQL.prototype.read(filter) : null;
}
return filter;}
},
"name",
"description",
"minScaleDenominator",
"maxScaleDenominator"
],
return filter;
},
defaultValue : null
}],
proxy : {
type : 'memory',
reader : {
type : 'json',
root : "rules"
}
}
});
});
2 changes: 1 addition & 1 deletion src/GeoExt/grid/column/Symbolizer.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Ext.define('GeoExt.grid.column.Symbolizer', {
var symbolType = "Polygon";
if (record) {
var symbolType = "Line";
var className = record.raw.geometry.CLASS_NAME;
var className = record.raw.geometry ? record.raw.geometry.CLASS_NAME : null;
if (className == "OpenLayers.Geometry.Point" ||
className == "OpenLayers.Geometry.MultiPoint") {
symbolType = "Point";
Expand Down
131 changes: 131 additions & 0 deletions tests/data/StyleStore.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<!DOCTYPE html>
<html debug="true">
<head>

<link rel="stylesheet" type="text/css" href="http://cdn.sencha.io/ext-4.1.0-gpl/resources/css/ext-all.css">
<script type="text/javascript" src="http://openlayers.org/api/2.12-rc3/OpenLayers.js"></script>
<script type="text/javascript" src="http://cdn.sencha.io/ext-4.1.0-gpl/ext-all-debug.js"></script>

<script type="text/javascript">
Ext.Loader.setConfig({
enabled:true,
disableCaching: false,
paths: {
Ext: "../../../ext/extjs-4.1.0/src",
GeoExt: "../../src/GeoExt"
}
});

Ext.require([
'GeoExt.data.StyleStore'
]);

var vectorSld = '<?xml version="1.0" encoding="ISO-8859-1"?><StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:gml="http://www.opengis.net/gml" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"><NamedLayer><Name>USA states population</Name><UserStyle><Name>population</Name><Title>Population in the United States</Title><Abstract>A sample filter that filters the United States into threecategories of population, drawn in different colors</Abstract><FeatureTypeStyle><Rule><Title>&lt; 2M</Title><ogc:Filter><ogc:PropertyIsLessThan> <ogc:PropertyName>PERSONS</ogc:PropertyName> <ogc:Literal>2000000</ogc:Literal></ogc:PropertyIsLessThan></ogc:Filter><PolygonSymbolizer> <Fill><!-- CssParameters allowed are fill (the color) and fill-opacity --><CssParameter name="fill">#4DFF4D</CssParameter><CssParameter name="fill-opacity">0.7</CssParameter> </Fill> </PolygonSymbolizer></Rule><Rule><Title>2M - 4M</Title><ogc:Filter><ogc:PropertyIsBetween><ogc:PropertyName>PERSONS</ogc:PropertyName><ogc:LowerBoundary><ogc:Literal>2000000</ogc:Literal></ogc:LowerBoundary><ogc:UpperBoundary><ogc:Literal>4000000</ogc:Literal></ogc:UpperBoundary></ogc:PropertyIsBetween></ogc:Filter><PolygonSymbolizer> <Fill><!-- CssParameters allowed are fill (the color) and fill-opacity --><CssParameter name="fill">#FF4D4D</CssParameter><CssParameter name="fill-opacity">0.7</CssParameter> </Fill> </PolygonSymbolizer></Rule><Rule><Title>&gt; 4M</Title><!-- like a linesymbolizer but with a fill too --><ogc:Filter><ogc:PropertyIsGreaterThan> <ogc:PropertyName>PERSONS</ogc:PropertyName> <ogc:Literal>4000000</ogc:Literal></ogc:PropertyIsGreaterThan></ogc:Filter><PolygonSymbolizer> <Fill><!-- CssParameters allowed are fill (the color) and fill-opacity --><CssParameter name="fill">#4D4DFF</CssParameter><CssParameter name="fill-opacity">0.7</CssParameter> </Fill> </PolygonSymbolizer></Rule><Rule><Title>Boundary</Title><LineSymbolizer><Stroke><CssParameter name="stroke-width">0.2</CssParameter></Stroke></LineSymbolizer><TextSymbolizer><Label><ogc:PropertyName>STATE_ABBR</ogc:PropertyName></Label><Font><CssParameter name="font-family">Times New Roman</CssParameter><CssParameter name="font-style">Normal</CssParameter><CssParameter name="font-size">14</CssParameter></Font><LabelPlacement><PointPlacement><AnchorPoint><AnchorPointX>0.5</AnchorPointX><AnchorPointY>0.5</AnchorPointY></AnchorPoint></PointPlacement></LabelPlacement></TextSymbolizer></Rule> </FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>';
var rasterSld = '<?xml version="1.0" encoding="ISO-8859-1"?><StyledLayerDescriptor version="1.0.0" xmlns="http://www.opengis.net/sld" xmlns:ogc="http://www.opengis.net/ogc" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.opengis.net/sld http://schemas.opengis.net/sld/1.0.0/StyledLayerDescriptor.xsd"><NamedLayer><Name>rain</Name><UserStyle><Name>rain</Name><Title>Rain distribution</Title><FeatureTypeStyle><Rule><RasterSymbolizer><Opacity>1.0</Opacity><ColorMap><ColorMapEntry color="#FF0000" quantity="0" /><ColorMapEntry color="#FFFFFF" quantity="100"/><ColorMapEntry color="#00FF00" quantity="2000"/><ColorMapEntry color="#0000FF" quantity="5000"/></ColorMap></RasterSymbolizer></Rule></FeatureTypeStyle></UserStyle></NamedLayer></StyledLayerDescriptor>';

var format = new OpenLayers.Format.SLD({multipleSymbolizers: true});

var vectorStyle = format.read(vectorSld).namedLayers["USA states population"].userStyles[0];
var rasterStyle = format.read(rasterSld).namedLayers["rain"].userStyles[0];

function test_constructor(t) {
t.plan(4);

var store1 = Ext.create('GeoExt.data.StyleStore', {
storeId: 'test1',
model: 'GeoExt.data.RasterStyleModel'
});

var store2 = Ext.create('GeoExt.data.StyleStore', {
storeId: 'test2',
model: 'GeoExt.data.VectorStyleModel'
});

t.ok(store1 instanceof GeoExt.data.StyleStore,
"ctor creates a GeoExt.data.StyleStore instance");

t.ok(store2 instanceof GeoExt.data.StyleStore,
"ctor creates a GeoExt.data.StyleStore instance");

t.eq(store1.model.$className, "GeoExt.data.RasterStyleModel",
"ctor associates the correct model type");

t.eq(store2.model.$className, "GeoExt.data.VectorStyleModel",
"ctor associates the correct model type");

store1.destroyStore();
store2.destroyStore();
}


function test_readRecords(t) {
t.plan(7);

var vecStore = Ext.create('GeoExt.data.StyleStore',{
storeId: 'test3',
data: vectorStyle
});

var rasStore = Ext.create('GeoExt.data.StyleStore',{
storeId: 'test4',
data: rasterStyle.rules[0].symbolizers[0]
});

t.eq(vecStore.model.$className,"GeoExt.data.VectorStyleModel",
'Correct model inferred from data');

t.eq(rasStore.model.$className,"GeoExt.data.RasterStyleModel",
'Correct model inferred from data');

t.eq(vecStore.getTotalCount(), 4,
"readRecords returns expected number of records");

t.eq(rasStore.getTotalCount(), 4,
"readRecords returns expected number of records");

t.ok(vecStore.getAt(0) instanceof GeoExt.data.VectorStyleModel,
"correct record instance type created");

t.ok(rasStore.getAt(0) instanceof GeoExt.data.RasterStyleModel,
"correct record instance type created");

t.ok(vecStore.getAt(0).get('symbolizers')[0] instanceof OpenLayers.Symbolizer,
"symbolizer has been reinitialized as needed");

vecStore.destroyStore();
rasStore.destroyStore();
}

function test_storeToData(t) {
t.plan(4);

var vecStore = Ext.create('GeoExt.data.StyleStore',{
storeId: 'test5',
data: vectorStyle,
autoSync: true
});

var rasStore = Ext.create('GeoExt.data.StyleStore',{
storeId: 'test6',
data: rasterStyle.rules[0].symbolizers[0]
});

var filter = "PERSONS < 2000";
var rec = vecStore.getAt(0);
rec.set("filter", filter); // mapped to object with a converter
t.ok(rec.get('filter') instanceof OpenLayers.Filter, "CQL filter turned into a Filter instance");
t.eq(rec.get('filter').toString(), filter, "Filter updated correctly");

rasStore.getAt(1).set("filter", "50000");
rasStore.commitChanges();
rec = rasStore.getAt(3);
t.eq(rec.get("filter"), 50000, "ColorMap entries sorted in ascending order");
t.eq(typeof rec.get("filter"), "number", "quantity stored as number");

vecStore.destroyStore();
rasStore.destroyStore();
}
</script>
<body>
</body>
</html>
2 changes: 2 additions & 0 deletions tests/list-tests.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@
<li>data/reader/WmsDescribeLayer.html</li>
<li>data/WmsDescribeLayerStore.html</li>
<li>data/ScaleStore.html</li>
<li>data/StyleStore.html</li>
<li>data/proxy/Protocol.html</li>
<li>FeatureRenderer.html</li>
<li>Form.html</li>
<li>form/action/Search.html</li>
Expand Down

0 comments on commit e463a98

Please sign in to comment.