[Users] TreePanel with Vector Legend

Adam Ratcliffe adam at prema.co.nz
Mon Aug 16 11:25:29 CEST 2010


Hi Andreas,

Thanks for the feedback.  I did strike a few issues with the
TreeNodeUI not being an Ext.Component so your approach sounds like the
way to go.  I'll get back in touch once I have something working.

Cheers
Adam

On Mon, Aug 16, 2010 at 8:09 PM, Andreas Hocevar <ahocevar at opengeo.org> wrote:
> 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