33 changes: 32 additions & 1 deletion src/script/locale/no.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,9 @@ GeoExt.Lang.add("no", {
styleWindowTitle: "Bruker Stil: {0}",
ruleWindowTitle: "Stil regel: {0}",
stylesFieldsetTitle: "Stiler",
rulesFieldsetTitle: "Regler"
rulesFieldsetTitle: "Regler",
classifyStyleText: "Classify",
classifyStyleTip: "Classify the layer based on attributes"
},

"gxp.LayerUploadPanel.prototype": {
Expand Down Expand Up @@ -427,6 +429,35 @@ GeoExt.Lang.add("no", {
doneText: "Ferdig",
titleText: "Legg til Feeds",
maxResultsText: "Max elementer"
},

"gxp.ClassificationPanel.prototype": {
classNumberText: 'Classes',
classifyText: "Classify",
rampBlueText: "Blue",
rampRedText: "Red",
rampOrangeText: "Orange",
rampJetText: "Blue-Red",
rampGrayText: "Gray",
rampRandomText: "Random",
rampCustomText: "Custom",
selectColorText: "Select colors",
colorStartText: "Start Color",
colorEndText: "End Color",
colorRampText: 'Color Ramp',
methodText: "Method",
methodUniqueText: "Unique Values",
methodQuantileText: "Quantile",
methodEqualText: "Equal Intervals",
methodJenksText: "Jenks Natural Breaks",
selectMethodText: "Select method",
standardDeviationText: "Standard Deviations",
attributeText: "Attribute",
selectAttributeText: "Select attribute",
startColor: "#FEE5D9",
endColor: "#A50F15",
generateRulesText: "Apply",
reverseColorsText: "Reverse colors"
}

});
33 changes: 32 additions & 1 deletion src/script/locale/pl.js
Original file line number Diff line number Diff line change
Expand Up @@ -352,7 +352,9 @@ GeoExt.Lang.add("pl", {
styleWindowTitle: "Styl użytkownika: {0}",
ruleWindowTitle: "Reguła stylu: {0}",
stylesFieldsetTitle: "Style",
rulesFieldsetTitle: "Reguły"
rulesFieldsetTitle: "Reguły",
classifyStyleText: "Classify",
classifyStyleTip: "Classify the layer based on attributes"
},

"gxp.LayerUploadPanel.prototype": {
Expand Down Expand Up @@ -403,6 +405,35 @@ GeoExt.Lang.add("pl", {
doneText: "Gotowe",
titleText: "Dodaj kanały",
maxResultsText: "Rzeczy Max"
},

"gxp.ClassificationPanel.prototype": {
classNumberText: 'Classes',
classifyText: "Classify",
rampBlueText: "Blue",
rampRedText: "Red",
rampOrangeText: "Orange",
rampJetText: "Blue-Red",
rampGrayText: "Gray",
rampRandomText: "Random",
rampCustomText: "Custom",
selectColorText: "Select colors",
colorStartText: "Start Color",
colorEndText: "End Color",
colorRampText: 'Color Ramp',
methodText: "Method",
methodUniqueText: "Unique Values",
methodQuantileText: "Quantile",
methodEqualText: "Equal Intervals",
methodJenksText: "Jenks Natural Breaks",
selectMethodText: "Select method",
standardDeviationText: "Standard Deviations",
attributeText: "Attribute",
selectAttributeText: "Select attribute",
startColor: "#FEE5D9",
endColor: "#A50F15",
generateRulesText: "Apply",
reverseColorsText: "Reverse colors"
}

});
33 changes: 32 additions & 1 deletion src/script/locale/ru.js
Original file line number Diff line number Diff line change
Expand Up @@ -374,7 +374,9 @@ GeoExt.Lang.add("ru", {
styleWindowTitle: "Пользовательский стиль: {0}",
ruleWindowTitle: "Правило стиля: {0}",
stylesFieldsetTitle: "Стили",
rulesFieldsetTitle: "Правила"
rulesFieldsetTitle: "Правила",
classifyStyleText: "Classify",
classifyStyleTip: "Classify the layer based on attributes"
},

"gxp.LayerUploadPanel.prototype": {
Expand Down Expand Up @@ -427,6 +429,35 @@ GeoExt.Lang.add("ru", {
doneText: "Готово",
titleText: "Добавить каналы",
maxResultsText: "Максимальное количество элементов"
},

"gxp.ClassificationPanel.prototype": {
classNumberText: 'Classes',
classifyText: "Classify",
rampBlueText: "Blue",
rampRedText: "Red",
rampOrangeText: "Orange",
rampJetText: "Blue-Red",
rampGrayText: "Gray",
rampRandomText: "Random",
rampCustomText: "Custom",
selectColorText: "Select colors",
colorStartText: "Start Color",
colorEndText: "End Color",
colorRampText: 'Color Ramp',
methodText: "Method",
methodUniqueText: "Unique Values",
methodQuantileText: "Quantile",
methodEqualText: "Equal Intervals",
methodJenksText: "Jenks Natural Breaks",
selectMethodText: "Select method",
standardDeviationText: "Standard Deviations",
attributeText: "Attribute",
selectAttributeText: "Select attribute",
startColor: "#FEE5D9",
endColor: "#A50F15",
generateRulesText: "Apply",
reverseColorsText: "Reverse colors"
}

});
16 changes: 8 additions & 8 deletions src/script/plugins/WMSRasterStylesDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ gxp.plugins.WMSRasterStylesDialog = {
/** private: method[addRule]
*/
addRule: function() {
var legend = this.items.get(2).items.get(0);
var legend = this.getComponent("rulesfieldset").items.get(0);
if (this.isRaster) {
legend.rules.push(this.createPseudoRule());
// we need either zero or at least two rules
Expand All @@ -73,7 +73,7 @@ gxp.plugins.WMSRasterStylesDialog = {
*/
removeRule: function() {
if (this.isRaster) {
var legend = this.items.get(2).items.get(0);
var legend = this.getComponent("rulesfieldset").items.get(0);
var rule = this.selectedRule;
legend.unselect();
legend.rules.remove(rule);
Expand All @@ -88,7 +88,7 @@ gxp.plugins.WMSRasterStylesDialog = {
/** private: method[duplicateRule]
*/
duplicateRule: function() {
var legend = this.items.get(2).items.get(0);
var legend = this.getComponent("rulesfieldset").items.get(0);
if (this.isRaster) {
legend.rules.push(this.createPseudoRule({
quantity: this.selectedRule.name,
Expand Down Expand Up @@ -156,7 +156,7 @@ gxp.plugins.WMSRasterStylesDialog = {
allowBlank: false,
fieldLabel: "Quantity",
validator: function(value) {
var rules = me.items.get(2).items.get(0).rules;
var rules = this.getComponent("rulesfieldset").items.get(0).rules;
for (var i=rules.length-1; i>=0; i--) {
if (rule !== rules[i] && rules[i].name == value) {
return "Quantity " + value + " is already defined";
Expand Down Expand Up @@ -235,7 +235,7 @@ gxp.plugins.WMSRasterStylesDialog = {
*/
savePseudoRules: function() {
var style = this.selectedStyle;
var legend = this.items.get(2).items.get(0);
var legend = this.getComponent("rulesfieldset").items.get(0);
var userStyle = style.get("userStyle");

var pseudoRules = legend.rules;
Expand Down Expand Up @@ -319,7 +319,7 @@ gxp.plugins.WMSRasterStylesDialog = {
createPseudoRule: function(colorMapEntry) {
var quantity = -1;
if (!colorMapEntry) {
var fieldset = this.items.get(2);
var fieldset = this.getComponent("rulesfieldset");
if (fieldset.items) {
rules = fieldset.items.get(0).rules;
for (var i=rules.length-1; i>=0; i--) {
Expand Down Expand Up @@ -349,9 +349,9 @@ gxp.plugins.WMSRasterStylesDialog = {
* the last rule.
*/
updateRuleRemoveButton: function() {
this.items.get(3).items.get(1).setDisabled(!this.selectedRule ||
this.getComponent("rulestoolbar").items.get(1).setDisabled(!this.selectedRule ||
(this.isRaster === false &&
this.items.get(2).items.get(0).rules.length <= 1));
this.getComponent("rulesfieldset").items.get(0).rules.length <= 1));
}

};
Expand Down
318 changes: 318 additions & 0 deletions src/script/widgets/ClassificationPanel.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,318 @@
/**
* Copyright (c) 2008-2011 The Open Planning Project
*
* Published under the GPL license.
* See https://github.com/opengeo/gxp/raw/master/license.txt for the full text
* of the license.
*/


/**
* @require OpenLayers/Renderer.js
* @require
*/


/** api: (define)
* module = gxp
* class = ClassificationPanel
* base_link = `Ext.TabPanel <http://extjs.com/deploy/dev/docs/?class=Ext.TabPanel>`_
*/
Ext.namespace("gxp");

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add at least some API docs, it doesn't have to be much, but something at least.


/** api: constructor
* .. class:: ClassificationPanel(config)
*
* Create a dialog for generating a classified styling for a layer,
* with options for specifying the number of classes,
* classification method, and choice of color ramps.
*/
gxp.ClassificationPanel = Ext.extend(Ext.Panel, {

hidden: false,
rulePanel: null,
customRamp: "Custom",

classNumberText: 'Classes',
classifyText: "Classify",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please also at least add this to the locale files (https://github.com/boundlessgeo/gxp/tree/master/src/script/locale), for the other languages just copy in the English language.

rampBlueText: "Blue",
rampRedText: "Red",
rampOrangeText: "Orange",
rampJetText: "Blue-Red",
rampGrayText: "Gray",
rampRandomText: "Random",
rampCustomText: "Custom",
selectColorText: "Select colors",
colorStartText: "Start Color",
colorEndText: "End Color",
colorRampText: 'Color Ramp',
methodText: "Method",
methodUniqueText: "Unique Values",
methodQuantileText: "Quantile",
methodEqualText: "Equal Intervals",
methodJenksText: "Jenks Natural Breaks",
selectMethodText: "Select method",
standardDeviationText: "Standard Deviations",
attributeText: "Attribute",
selectAttributeText: "Select attribute",
startColor: "#FEE5D9",
endColor: "#A50F15",
generateRulesText: "Apply",
reverseColorsText: "Reverse colors",


initComponent: function() {
var colorFieldPlugins;
if (this.rulePanel.colorManager) {
colorFieldPlugins = [new this.rulePanel.colorManager];
}

var colorPanel = new Ext.Panel({
hidden: true,
layout: 'form',
bodyStyle: {padding: "10px"},
border: false,
labelWidth: 70,
defaults: {
labelWidth: 70
},
items: [
{
xtype: "gxp_colorfield",
id: "choropleth_color_start",
name: "color_start",
fieldLabel: this.colorStartText,
emptyText: OpenLayers.Renderer.defaultSymbolizer.strokeColor,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be @require'd then

value: this.startColor,
defaultBackground: this.startColor,
plugins: colorFieldPlugins,
listeners: {
valid: function(field) {
this.rulePanel.rule[field.name] = field.getValue();
},
scope: this
}
},
{ xtype: "gxp_colorfield",
id: "choropleth_color_end",
name: "color_end",
fieldLabel: this.colorEndText,
emptyText: OpenLayers.Renderer.defaultSymbolizer.strokeColor,
value: this.endColor,
defaultBackground: this.endColor,
plugins: colorFieldPlugins,
listeners: {
valid: function(field) {
this.rulePanel.rule[field.name] = field.getValue();
},
scope: this
}
}
]
});

var classNumSelector = new Ext.ux.form.SpinnerField({
fieldLabel: this.classNumberText,
id: "choropleth_classes",
minValue: 2,
name: 'intervals',
defaultValue: 5,
width: 110,
listeners: {
'change':function(spinner, value){
this.rulePanel.rule[classNumSelector.name] = value;
},
scope: this
}
});

this.rulePanel.rule[classNumSelector.name] = classNumSelector.defaultValue;

var colorDropdown = new Ext.form.ComboBox({
id: 'choropleth_colorramp',
name: 'ramp',
fieldLabel: this.colorRampText,
store: new Ext.data.ArrayStore({
id: 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this needed?

fields: [
'colorramp',
'label'
],
data: [
['Blue',this.rampBlueText],
['Red', this.rampRedText],
['Orange', this.rampOrangeText],
['Jet', this.rampJetText],
['Gray', this.rampGrayText],
['Random', this.rampRandomText],
['Custom', this.rampCustomText]]
}),
mode: 'local',
width: 110,
displayField: "label",
valueField: "colorramp",
editable: false,
emptyText: this.selectColorText,
triggerAction: 'all',
disabled: false,
listeners: {
'select': function(cmb, data, idx) {
//If Custom: display start, end, middle color picker;
colorPanel.setVisible(cmb.value == this.customRamp);

switch(cmb.value) {
case "Blue":
this.rulePanel.rule["color_start"] = "#f7fbff";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should these colors be configurable or not needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Custom colors can be chosen by selecting the 'Custom' option in dropdown.

this.rulePanel.rule["color_end"] = "#08306b";
this.rulePanel.rule[cmb.name] = this.customRamp;
break;
case "Red":
this.rulePanel.rule["color_start"] = "#fff5f0";
this.rulePanel.rule["color_end"] = "#67000d";
this.rulePanel.rule[cmb.name] = this.customRamp;
break;
case "Orange":
this.rulePanel.rule["color_start"] = "#fff5eb";
this.rulePanel.rule["color_end"] = "#f16913";
this.rulePanel.rule[cmb.name] = this.customRamp;
break;
case "Jet":
this.rulePanel.rule[cmb.name] = "Jet";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please remove commented code

break;
default:
this.rulePanel.rule["color_mid"] = "";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is color_mid even used anywhere?

this.rulePanel.rule[cmb.name] = cmb.value;
}

},
scope: this
}
});

var methodDropdown = new Ext.form.ComboBox({
id: 'choropleth_method',
name: 'method',
fieldLabel: this.methodText,
store: new Ext.data.ArrayStore({
id: 0,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is this even a config in ExtJS?

mode: 'local',
autoDestroy: true,
storeId: 'method_array_store',
fields: [
'value', 'label'
],
data: [
['uniqueInterval', this.methodUniqueText],
['quantile', this.methodQuantileText],
['equalInterval', this.methodEqualText],
['jenks', this.methodJenksText]
]
}),
displayField: 'label',
valueField: 'value',
mode: 'local',
width: 110,
editable: false,
emptyText: this.selectMethodText,
triggerAction: 'all',
disabled: false,
listeners: {
'select': function(cmb, data, idx) {

//If uniqueInterval: disable # classes
classNumSelector.setDisabled(cmb.value == "uniqueInterval");
this.rulePanel.rule[cmb.name] = cmb.value;
},
scope: this
}
});

var attributeDropdown = new Ext.form.ComboBox({
id: 'choropleth_attribute',
name: 'attribute',
fieldLabel: this.attributeText,
store: this.rulePanel.attributes,
displayField: 'name',
valueField: 'name',
triggerAction: 'all',
mode: 'local',
width: 110,
editable: false,
emptyText: this.selectAttributeText,
disabled: false,
listeners: {
'select': function(cmb, data, idx) {
this.rulePanel.rule[cmb.name] = cmb.value;
methodDropdown.clearValue();
var methodStore = methodDropdown.getStore();
for (var i = 0, ii=methodStore.data.length; i <ii ; i++) {
methodStore.getAt(i).disabled = (cmb.getStore().getAt(idx).get("type") == "xsd:string" ? methodStore.getAt(i).get("value") != "uniqueInterval": false);
}
methodStore.loadData(cmb.getStore().getAt(idx).get("type") == "xsd:string" ?
[['uniqueInterval',this.methodUniqueText]]
:[['uniqueInterval',this.methodUniqueText],
['quantile', this.methodQuantileText],
['equalInterval',this.methodEqualText],
['jenks', this.methodJenksText]]
);
},
scope: this
}
});

this.items = [
{
xtype:"fieldset",
title:this.classifyText,
labelWidth:85,
style:"margin-bottom: 0;",
items: [
//Dropdown: attributes
attributeDropdown,
//Dropdown: classification mode
methodDropdown,
//Classes, use http://dev.sencha.com/deploy/ext-3.4.0/examples/spinner/spinner.html
classNumSelector,
//Dropdown: color ramp
colorDropdown,
//Checkbox: Generate classification rules
{
xtype: 'checkbox',
name: 'reverse',
checked: false,
ctCls: 'x-checkbox-inline',
hideLabel: true,
labelSeparator: '',
labelStyle: 'display:inline;',
boxLabel: this.reverseColorsText,
handler: function(item, e)
{
this.rulePanel.rule['reverse'] = item.checked;
},
scope: this
},
//Text field / Ext.menu.ColorMenu: start color
colorPanel,
{
xtype: 'button',
name: 'apply',
text: this.generateRulesText,
fieldLabel: '&nbsp;',
style: 'margin-top:10px;',
labelSeparator: '',
handler: function (item, e) {
this.rulePanel.fireEvent("change", this.rulePanel, this.rulePanel.rule);
},
scope: this
}
]
}
]
gxp.ClassificationPanel.superclass.initComponent.call(this);
}

});

/** api: xtype = gxp_classificationpanel */
Ext.reg('gxp_classificationpanel', gxp.ClassificationPanel);
45 changes: 43 additions & 2 deletions src/script/widgets/RulePanel.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
* @include widgets/LineSymbolizer.js
* @include widgets/PointSymbolizer.js
* @include widgets/FilterBuilder.js
* @include widgets/ClassificationPanel.js
*/

/** api: (define)
Expand Down Expand Up @@ -125,7 +126,13 @@ gxp.RulePanel = Ext.extend(Ext.TabPanel, {
* are available to the <scaleSliderTemplate>.
*/
modifyScaleTipContext: Ext.emptyFn,


/** private: property[classifyEnabled]
* ``Boolean`` Enable the ClassificationPanel widget
* Default is false.
*/
classifyEnabled: false,

/** i18n */
labelFeaturesText: "Label Features",
labelsText: "Labels",
Expand Down Expand Up @@ -238,7 +245,7 @@ gxp.RulePanel = Ext.extend(Ext.TabPanel, {
this.items = [{
title: this.basicText,
autoScroll: true,
items: [this.createHeaderPanel(), this.createSymbolizerPanel()]
items: [this.createHeaderPanel(), this.createSymbolizerPanel(), this.createClassificationPanel()]
}, this.items[0], {
title: this.advancedText,
defaults: {
Expand Down Expand Up @@ -291,6 +298,7 @@ gxp.RulePanel = Ext.extend(Ext.TabPanel, {
xtype: "fieldset",
title: this.limitByConditionText,
checkboxToggle: true,
hidden: this.classifyEnabled,
collapsed: !(this.rule && this.rule.filter),
autoHeight: true,
items: [this.filterBuilder],
Expand Down Expand Up @@ -326,6 +334,15 @@ gxp.RulePanel = Ext.extend(Ext.TabPanel, {
tabchange: function(panel, tab) {
tab.doLayout();
},
afterRender: function() {
if (this.classifyEnabled) {
var symbolizer = this.items.items[0].items.items[1];

//Hide fill color
var element = Ext.getCmp(Ext.get(symbolizer.id).child('[name=color]').id);
element.setVisible(false);
}
},
scope: this
});

Expand Down Expand Up @@ -413,6 +430,7 @@ gxp.RulePanel = Ext.extend(Ext.TabPanel, {
width: 150,
items: [{
xtype: "textfield",
hidden: this.classifyEnabled,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this property should be documented in this class?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

fieldLabel: this.nameText,
anchor: "95%",
value: this.rule && (this.rule.title || this.rule.name || ""),
Expand Down Expand Up @@ -489,6 +507,29 @@ gxp.RulePanel = Ext.extend(Ext.TabPanel, {

},

/** private: method[createClassificationPanel]
* Interface for specifying classification criteria,
* Only displays if GeoServer sldService community module
* is installed.
*/
createClassificationPanel: function() {

if (this.classifyEnabled) {
this.rule["classify"] = true;
}

return new gxp.ClassificationPanel({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this needs a @require at the top of this file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added @include for widgets/ClassificationPanel.js

bodyStyle: {padding: "10px"},
border: false,
labelWidth: 70,
defaults: {
labelWidth: 70
},
hidden: !this.classifyEnabled,
rulePanel: this
});
},

/** private: method[getSymbolTypeFromRule]
* :arg rule: `OpenLayers.Rule`
* :return: `String` "Point", "Line" or "Polygon" (or undefined if none
Expand Down
290 changes: 258 additions & 32 deletions src/script/widgets/WMSStylesDialog.js

Large diffs are not rendered by default.

13 changes: 13 additions & 0 deletions src/theme/all.css
Original file line number Diff line number Diff line change
Expand Up @@ -605,3 +605,16 @@ div.olMap div.gx-overlay-playback {
.thumb-mapbox-world-print {
background-image:url('img/thumbs/mapbox/world-print.png');
}
.x-btn .gradient {
background-image: url(img/gradient.png);
}
.x-center-toolbar{
border: 1px solid #A9BFD3;
margin-bottom: 10px;
}
.x-toolbar-ct{
width:100% !important;
}
.x-checkbox-inline label{
display:inline;
}
Binary file added src/theme/img/gradient.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.