[Users] TreePanel with Vector Legend

Andreas Hocevar ahocevar at opengeo.org
Mon Aug 16 10:09:13 CEST 2010


Hi,

although your progress here is impressive, I think it would have been simpler to add the VectorLegend as a component, after creating a generic tree node that can render an Ext.Component (which the VectorLegend is). This is covered by http://trac.geoext.org/ticket/139, and there is a working patch already. My objection to this patch was that extending nodes with different mixins can become complicated, so I proposed http://trac.geoext.org/ticket/185, which also has a working patch, plus patches from others that show how node additions can be created easily based on my patch.

If you want to try this approach, I'll gladly assist.

Regards,
Andreas.

On Aug 16, 2010, at 01:44 , Adam Ratcliffe wrote:

> Hi Andreas,
> 
> I had sometime over the weekend to start looking into how to implement
> this.  Below is my initial attempt, which while working, I'm not
> completely happy with.  Maybe you or somebody on the else on the list
> can suggest some improvements?
> 
> Some of the issues that I had were:
> 
> - My class duplicates code from GeoExt.VectorLegend
> 
> - I needed to override GeoExt.FeatureRenderer.onRender() so that the
> wrapper element that's created for the legend swatch is an inline
> element rather than a block-level element.  It would be helpful if
> GeoExt.FeatureRenderer allowed the element type to be specified via
> the 'autoEl' config option like other ExtJS components.
> 
> - I had issues with vertical alignment of the legend swatch relative
> to the node checkbox and label text.  I was able to align these
> elements satisfactorily under FF and Safari using the styles below - I
> haven't tested in IE yet.
> 
> Styles
> ----------
> 
> .x-tree-node-legend {
>    height: 18px;
> }
> 
> .x-tree-node-legend input {
>    margin-left: 2px !important;
>    vertical-align: top !important;
> }
> 
> .x-tree-node-legend .x-tree-node-anchor span {
>    vertical-align: top !important;
> }
> 
> Script
> ---------
> 
> GeoExt.tree.VectorLayerNodeUI = Ext.extend(GeoExt.tree.LayerNodeUI, {
> 
>    constructor: function(config) {
>        GeoExt.tree.VectorLayerNodeUI.superclass.constructor.apply(this,
> arguments);
> 
>        if (!this.symbolType) {
>            if (this.feature) {
>                this.symbolType = this.symbolTypeFromFeature(this.feature);
>            } else if (this.node.layer) {
>                if (this.node.layer.geometryType) {
>                    this.symbolType =
> this.symbolTypeFromGeometry(this.node.layer.geometryType);
>                } else if (this.node.layer.features.length > 0) {
>                    var feature = this.node.layer.features[0].clone();
>                    feature.attributes = {};
>                    this.feature = feature;
>                    this.symbolType = this.symbolTypeFromFeature(this.feature);
>                } else {
>                    this.node.layer.events.on({
>                        featuresadded: this.onFeaturesAdded,
>                        scope: this
>                    });
>                }
>            }
>        }
> 
>        this.setRules();
>    },
> 
>    symbolTypeFromGeometry: function(geometry) {
>        var symbolType = geometry.prototype.CLASS_NAME.split('.').pop();
>        return (symbolType == 'LineString') ? 'Line' : symbolType;
>    },
> 
>    symbolTypeFromFeature: function(feature) {
>        var match = feature.geometry.CLASS_NAME.match(/Point|Line|Polygon/);
>        return (match && match[0]) || "Point";
>    },
> 
>    onFeaturesAdded: function() {
>        this.node.layer.events.un({
>            featuresadded: this.onFeaturesAdded,
>            scope: this
>        });
>        var feature = this.node.layer.features[0].clone();
>        feature.attributes = {};
>        this.feature = feature;
>        this.symbolType = this.symbolTypeFromFeature(this.feature);
>        if (!this.rules) {
>            this.setRules();
>        }
>        this.update();
>    },
> 
>    update: function() {
>        if (this.symbolType && this.rules) {
>            this.createRuleRenderer(this.rules[0],
> this.legendWrap).render(this.elNode, 2);
>        }
>    },
> 
>    setRules: function() {
>        var style = this.node.layer.styleMap &&
> this.node.layer.styleMap.styles["default"];
>        if (!style) {
>            style = new OpenLayers.Style();
>        }
>        if (style.rules.length === 0) {
>            this.rules = [
>                new OpenLayers.Rule({
>                    symbolizer: style.createSymbolizer(this.feature)
>                })
>            ];
>        } else {
>            this.rules = style.rules;
>        }
>    },
> 
>    createRuleRenderer: function(rule) {
>        var symbolizer = rule.symbolizer;
>        if (symbolizer[this.symbolType]) {
>            symbolizer = symbolizer[this.symbolType];
>        }
>        return new GeoExt.FeatureRenderer({
>            resolution: 1,
>            width: 18,
>            height: 18,
>            symbolType: this.symbolType,
>            symbolizers: [symbolizer],
>            // override onRender() so that the vector element can
>            // be wrapped with an inline element in place of a block element
>            onRender: function(ct, position) {
>                if(!this.el) {
>                    this.el = document.createElement('span');
>                    this.el.className = 'legend-wrap';
>                    this.el.id = this.getId();
>                }
>                if(!this.renderer || !this.renderer.supported()) {
>                    this.assignRenderer();
>                }
>                this.renderer.map = {
>                    getResolution: (function() {
>                        return this.resolution;
>                    }).createDelegate(this)
>                };
>                this.drawFeature();
>                GeoExt.FeatureRenderer.superclass.onRender.apply(this,
> arguments);
>            }
>        });
>    },
> 
>    renderElements : function(n, a, targetNode, bulkRender){
>        // add some indent caching, this helps performance when
> rendering a large tree
>        this.indentMarkup = n.parentNode ?
> n.parentNode.ui.getChildIndent() : '';
> 
>        var cb = Ext.isBoolean(a.checked),
>            nel,
>            href = a.href ? a.href : Ext.isGecko ? "" : "#",
>            buf = ['<li class="x-tree-node"><div
> ext:tree-node-id="',n.id,'" class="x-tree-node-el x-tree-node-leaf
> x-tree-node-legend x-unselectable ', a.cls,'" unselectable="on">',
>            '<span class="x-tree-node-indent">',this.indentMarkup,"</span>",
>            '<img src="', this.emptyIcon, '" class="x-tree-ec-icon
> x-tree-elbow" />',
>            cb ? ('<input class="x-tree-node-cb" type="checkbox" ' +
> (a.checked ? 'checked="checked" />' : '/>')) : '',
>            '<a hidefocus="on" class="x-tree-node-anchor"
> href="',href,'" tabIndex="1" ',
>             a.hrefTarget ? ' target="'+a.hrefTarget+'"' : "", '><span
> unselectable="on">',n.text,"</span></a></div>",
>            '<ul class="x-tree-node-ct" style="display:none;"></ul>',
>            "</li>"].join('');
> 
>        if(bulkRender !== true && n.nextSibling && (nel =
> n.nextSibling.ui.getEl())){
>            this.wrap = Ext.DomHelper.insertHtml("beforeBegin", nel, buf);
>        }else{
>            this.wrap = Ext.DomHelper.insertHtml("beforeEnd", targetNode, buf);
>        }
> 
>        this.elNode = this.wrap.childNodes[0];
>        this.ctNode = this.wrap.childNodes[1];
>        var cs = this.elNode.childNodes;
>        this.indentNode = cs[0];
>        this.ecNode = cs[1];
>        var index = 2;
>        if(cb){
>            this.checkbox = cs[2];
>            // fix for IE6
>            this.checkbox.defaultChecked = this.checkbox.checked;
>            index++;
>        }
>        this.anchor = cs[index];
>        this.textNode = cs[index].firstChild;
> 
>        if(this.symbolType) {
>            this.createRuleRenderer(this.rules[0]).render(this.elNode, 2);
>        }
>    }
> });
> 
> Cheers
> Adam
> 
> Cheers
> Adam
> 
> On Mon, Aug 2, 2010 at 7:44 PM, Andreas Hocevar <ahocevar at opengeo.org> wrote:
>> Oops, sorry. I had missed the "TreePanel" part of your original mail (thought you wanted a VectorLegend in your LegendPanel). At this point, you cannot render a legend with a tree node. There are several tickets with patches already, which may help you:
>> 
>> http://trac.geoext.org/ticket/185
>> http://trac.geoext.org/ticket/139
>> 
>> Regards,
>> Andreas.
>> 
>> On Aug 2, 2010, at 09:27 , Adam Ratcliffe wrote:
>> 
>>> That's great.
>>> 
>>> Just one question, how do I configure my TreePanel to create the node
>>> with a vector legend instead of an icon, my current tree configuration
>>> looks like this:
>>> 
>>>        var config = {
>>>            autoScroll: true,
>>>            animate: true,
>>>            border: false,
>>>            region: 'center',
>>>            stateful: true,
>>>            root: new GeoExt.tree.LayerContainer({
>>>                text: 'Layers',
>>>                loader: new GeoExt.tree.LayerLoader({
>>>                    store: this.layerStore,
>>>                    createNode: function(attr) {
>>>                        var layer = attr.layer;
>>>                        attr.iconCls = layer.gsGeometryType ? 'icon_'
>>> + layer.gsGeometryType.toLowerCase() : 'icon_point';
>>>                        return
>>> GeoExt.tree.LayerLoader.prototype.createNode.call(this, attr);
>>>                    }
>>>                }),
>>>                layerStore: this.layerStore,
>>>                leaf: false,
>>>                expanded: true
>>>            })
>>> }
>>> 
>>> Cheers
>>> Adam
>>> 
>>> On Mon, Aug 2, 2010 at 6:13 PM, Andreas Hocevar <ahocevar at opengeo.org> wrote:
>>>> Hi,
>>>> 
>>>> On Aug 2, 2010, at 05:41 , Adam Ratcliffe wrote:
>>>> 
>>>>> I'd like to dynamically render symbols based upon the layer geometry
>>>>> type and styles in a TreePanel similar to the vector legend example
>>>>> here: http://dev.geoext.org/trunk/geoext/examples/vector-legend.html
>>>>> 
>>>>> Is this possible?
>>>> 
>>>> Yes! Just configure your vector layer with a StyleMap. The VectorLegend will be built from the style and rules of the "default" render intent.
>>>> 
>>>> Regards,
>>>> Andreas.
>>>> 
>>>>> 
>>>>> Cheers
>>>>> Adam
>>>>> _______________________________________________
>>>>> Users mailing list
>>>>> Users at geoext.org
>>>>> http://www.geoext.org/cgi-bin/mailman/listinfo/users
>>>> 
>>>> 
>>>> 
>>>> --
>>>> Andreas Hocevar
>>>> OpenGeo - http://opengeo.org/
>>>> Expert service straight from the developers.
>>>> 
>>>> 
>> 
>> --
>> Andreas Hocevar
>> OpenGeo - http://opengeo.org/
>> Expert service straight from the developers.
>> 
>> 
> _______________________________________________
> Users mailing list
> Users at geoext.org
> http://www.geoext.org/cgi-bin/mailman/listinfo/users

-- 
Andreas Hocevar
OpenGeo - http://opengeo.org/
Expert service straight from the developers.



More information about the Users mailing list