1 | /** |
---|
2 | * Copyright (c) 2008-2010 The Open Source Geospatial Foundation |
---|
3 | * |
---|
4 | * Published under the BSD license. |
---|
5 | * See http://svn.geoext.org/core/trunk/geoext/license.txt for the full text |
---|
6 | * of the license. |
---|
7 | */ |
---|
8 | |
---|
9 | /** |
---|
10 | * @include GeoExt/widgets/FeatureRenderer.js |
---|
11 | * @requires GeoExt/widgets/LayerLegend.js |
---|
12 | */ |
---|
13 | |
---|
14 | /** api: (define) |
---|
15 | * module = GeoExt |
---|
16 | * class = VectorLegend |
---|
17 | */ |
---|
18 | |
---|
19 | /** api: (extends) |
---|
20 | * GeoExt/widgets/LayerLegend.js |
---|
21 | */ |
---|
22 | |
---|
23 | Ext.namespace('GeoExt'); |
---|
24 | |
---|
25 | /** api: constructor |
---|
26 | * .. class:: VectorLegend(config) |
---|
27 | * |
---|
28 | * Create a vector legend. |
---|
29 | */ |
---|
30 | GeoExt.VectorLegend = Ext.extend(GeoExt.LayerLegend, { |
---|
31 | |
---|
32 | /** api: config[layerRecord] |
---|
33 | * :class:`GeoExt.data.LayerRecord` |
---|
34 | * The record containing a vector layer that this legend will be based on. |
---|
35 | * One of ``layerRecord``, ``layer``, or ``rules`` must be specified in |
---|
36 | * the config. |
---|
37 | */ |
---|
38 | layerRecord: null, |
---|
39 | |
---|
40 | /** api: config[layer] |
---|
41 | * ``OpenLayers.Layer.Vector`` |
---|
42 | * The layer that this legend will be based on. One of ``layer``, |
---|
43 | * ``rules``, or ``layerRecord`` must be specified in the config. |
---|
44 | */ |
---|
45 | layer: null, |
---|
46 | |
---|
47 | /** api: config[rules] |
---|
48 | * ``Array(OpenLayers.Rule)`` |
---|
49 | * List of rules. One of ``rules``, ``layer``, or ``layerRecord`` must be |
---|
50 | * specified in the config. The ``symbolType`` property must also be |
---|
51 | * provided if only ``rules`` are given in the config. |
---|
52 | */ |
---|
53 | rules: null, |
---|
54 | |
---|
55 | /** api: config[symbolType] |
---|
56 | * ``String`` |
---|
57 | * The symbol type for legend swatches. Must be one of ``"Point"``, |
---|
58 | * ``"Line"``, or ``"Polygon"``. If not provided, the ``layer`` or |
---|
59 | * ``layerRecord`` config property must be specified, and the geometry type |
---|
60 | * of the first feature found on the layer will be used. If a rule does |
---|
61 | * not have a symbolizer for ``symbolType``, we look at the symbolizers |
---|
62 | * for the rule, and see if it has a ``"Point"``, ``"Line"`` or |
---|
63 | * ``"Polygon"`` symbolizer, which we use for rendering a swatch of the |
---|
64 | * respective geometry type. |
---|
65 | */ |
---|
66 | symbolType: null, |
---|
67 | |
---|
68 | /** api: config[untitledPrefix] |
---|
69 | * ``String`` |
---|
70 | * The prefix to use as a title for rules with no title or |
---|
71 | * name. Default is ``"Untitled "``. Prefix will be appended with a |
---|
72 | * number that corresponds to the index of the rule (1 for first rule). |
---|
73 | */ |
---|
74 | untitledPrefix: "Untitled ", |
---|
75 | |
---|
76 | /** api: config[clickableSymbol] |
---|
77 | * ``Boolean`` |
---|
78 | * Set cursor style to "pointer" for symbolizers. Register for |
---|
79 | * the ``symbolclick`` event to handle clicks. Note that click events |
---|
80 | * are fired regardless of this value. If ``false``, no cursor style will |
---|
81 | * be set. Default is ``false``. |
---|
82 | */ |
---|
83 | clickableSymbol: false, |
---|
84 | |
---|
85 | /** api: config[clickableTitle] |
---|
86 | * ``Boolean`` |
---|
87 | * Set cursor style to "pointer" for rule titles. Register for |
---|
88 | * the ``titleclick`` event to handle clicks. Note that click events |
---|
89 | * are fired regardless of this value. If ``false``, no cursor style will |
---|
90 | * be set. Default is ``false``. |
---|
91 | */ |
---|
92 | clickableTitle: false, |
---|
93 | |
---|
94 | /** api: config[selectOnClick] |
---|
95 | * ``Boolean`` |
---|
96 | * Set to true if a rule should be selected by clicking on the |
---|
97 | * symbol or title. Selection will trigger the ruleselected event, and |
---|
98 | * a click on a selected rule will unselect it and trigger the |
---|
99 | * ``ruleunselected`` event. Default is ``false``. |
---|
100 | */ |
---|
101 | selectOnClick: false, |
---|
102 | |
---|
103 | /** api: config[enableDD] |
---|
104 | * ``Boolean`` |
---|
105 | * Allow drag and drop of rules. Default is ``false``. |
---|
106 | */ |
---|
107 | enableDD: false, |
---|
108 | |
---|
109 | /** api: config[bodyBorder] |
---|
110 | * ``Boolean`` |
---|
111 | * Show a border around the legend panel. Default is ``false``. |
---|
112 | */ |
---|
113 | bodyBorder: false, |
---|
114 | |
---|
115 | /** private: property[feature] |
---|
116 | * ``OpenLayers.Feature.Vector`` |
---|
117 | * Cached feature for rendering. |
---|
118 | */ |
---|
119 | feature: null, |
---|
120 | |
---|
121 | /** private: property[selectedRule] |
---|
122 | * ``OpenLayers.Rule`` |
---|
123 | * The rule that is currently selected. |
---|
124 | */ |
---|
125 | selectedRule: null, |
---|
126 | |
---|
127 | /** private: property[currentScaleDenominator] |
---|
128 | * ``Number`` |
---|
129 | * The current scale denominator of any map associated with this |
---|
130 | * legend. Use :meth`setCurrentScaleDenominator` to change this. If not |
---|
131 | * set an entry for each rule will be rendered. If set, only rules that |
---|
132 | * apply for the given scale will be rendered. |
---|
133 | */ |
---|
134 | currentScaleDenominator: null, |
---|
135 | |
---|
136 | /** private: method[initComponent] |
---|
137 | * Initializes the Vector legend. |
---|
138 | */ |
---|
139 | initComponent: function() { |
---|
140 | GeoExt.VectorLegend.superclass.initComponent.call(this); |
---|
141 | if (this.layerRecord) { |
---|
142 | this.layer = this.layerRecord.getLayer(); |
---|
143 | if (this.layer.map) { |
---|
144 | this.currentScaleDenominator = this.layer.map.getScale(); |
---|
145 | this.layer.map.events.on({ |
---|
146 | "zoomend": this.onMapZoom, |
---|
147 | scope: this |
---|
148 | }); |
---|
149 | } |
---|
150 | } |
---|
151 | |
---|
152 | // determine symbol type |
---|
153 | if (!this.symbolType) { |
---|
154 | if (this.feature) { |
---|
155 | this.symbolType = this.symbolTypeFromFeature(this.feature); |
---|
156 | } else if (this.layer) { |
---|
157 | if (this.layer.features.length > 0) { |
---|
158 | var feature = this.layer.features[0].clone(); |
---|
159 | feature.attributes = {}; |
---|
160 | this.feature = feature; |
---|
161 | this.symbolType = this.symbolTypeFromFeature(this.feature); |
---|
162 | } else { |
---|
163 | this.layer.events.on({ |
---|
164 | featuresadded: this.onFeaturesAdded, |
---|
165 | scope: this |
---|
166 | }); |
---|
167 | } |
---|
168 | } |
---|
169 | } |
---|
170 | |
---|
171 | // set rules if not provided |
---|
172 | if (this.layer && this.feature && !this.rules) { |
---|
173 | this.setRules(); |
---|
174 | } |
---|
175 | |
---|
176 | this.rulesContainer = new Ext.Container({ |
---|
177 | autoEl: {} |
---|
178 | }); |
---|
179 | |
---|
180 | this.add(this.rulesContainer); |
---|
181 | |
---|
182 | this.addEvents( |
---|
183 | /** api: event[titleclick] |
---|
184 | * Fires when a rule title is clicked. |
---|
185 | * |
---|
186 | * Listener arguments: |
---|
187 | * |
---|
188 | * * comp - :class:`GeoExt.VectorLegend`` This component. |
---|
189 | * * rule - ``OpenLayers.Rule`` The rule whose title was clicked. |
---|
190 | */ |
---|
191 | "titleclick", |
---|
192 | |
---|
193 | /** api: event[symbolclick] |
---|
194 | * Fires when a rule symbolizer is clicked. |
---|
195 | * |
---|
196 | * Listener arguments: |
---|
197 | * |
---|
198 | * * comp - :class:`GeoExt.VectorLegend`` This component. |
---|
199 | * * rule - ``OpenLayers.Rule`` The rule whose symbol was clicked. |
---|
200 | */ |
---|
201 | "symbolclick", |
---|
202 | |
---|
203 | /** api: event[ruleclick] |
---|
204 | * Fires when a rule entry is clicked (fired with symbolizer or |
---|
205 | * title click). |
---|
206 | * |
---|
207 | * Listener arguments: |
---|
208 | * |
---|
209 | * * comp - :class:`GeoExt.VectorLegend`` This component. |
---|
210 | * * rule - ``OpenLayers.Rule`` The rule that was clicked. |
---|
211 | */ |
---|
212 | "ruleclick", |
---|
213 | |
---|
214 | /** api: event[ruleselected] |
---|
215 | * Fires when a rule is clicked and ``selectOnClick`` is set to |
---|
216 | * ``true``. |
---|
217 | * |
---|
218 | * Listener arguments: |
---|
219 | * |
---|
220 | * * comp - :class:`GeoExt.VectorLegend`` This component. |
---|
221 | * * rule - ``OpenLayers.Rule`` The rule that was selected. |
---|
222 | */ |
---|
223 | "ruleselected", |
---|
224 | |
---|
225 | /** api: event[ruleunselected] |
---|
226 | * Fires when the selected rule is clicked and ``selectOnClick`` |
---|
227 | * is set to ``true``, or when a rule is unselected by selecting a |
---|
228 | * different one. |
---|
229 | * |
---|
230 | * Listener arguments: |
---|
231 | * |
---|
232 | * * comp - :class:`GeoExt.VectorLegend`` This component. |
---|
233 | * * rule - ``OpenLayers.Rule`` The rule that was unselected. |
---|
234 | */ |
---|
235 | "ruleunselected", |
---|
236 | |
---|
237 | /** api: event[rulemoved] |
---|
238 | * Fires when a rule is moved. |
---|
239 | * |
---|
240 | * Listener arguments: |
---|
241 | * |
---|
242 | * * comp - :class:`GeoExt.VectorLegend`` This component. |
---|
243 | * * rule - ``OpenLayers.Rule`` The rule that was moved. |
---|
244 | */ |
---|
245 | "rulemoved" |
---|
246 | ); |
---|
247 | |
---|
248 | this.update(); |
---|
249 | }, |
---|
250 | |
---|
251 | /** private: method[onMapZoom] |
---|
252 | * Listener for map zoomend. |
---|
253 | */ |
---|
254 | onMapZoom: function() { |
---|
255 | this.setCurrentScaleDenominator( |
---|
256 | this.layer.map.getScale() |
---|
257 | ); |
---|
258 | }, |
---|
259 | |
---|
260 | /** private: method[symbolTypeFromFeature] |
---|
261 | * :arg feature: ``OpenLayers.Feature.Vector`` |
---|
262 | * |
---|
263 | * Determine the symbol type given a feature. |
---|
264 | */ |
---|
265 | symbolTypeFromFeature: function(feature) { |
---|
266 | var match = feature.geometry.CLASS_NAME.match(/Point|Line|Polygon/); |
---|
267 | return (match && match[0]) || "Point"; |
---|
268 | }, |
---|
269 | |
---|
270 | /** private: method[onFeaturesAdded] |
---|
271 | * Set as a one time listener for the ``featuresadded`` event on the layer |
---|
272 | * if it was provided with no features originally. |
---|
273 | */ |
---|
274 | onFeaturesAdded: function() { |
---|
275 | this.layer.events.un({ |
---|
276 | featuresadded: this.onFeaturesAdded, |
---|
277 | scope: this |
---|
278 | }); |
---|
279 | var feature = this.layer.features[0].clone(); |
---|
280 | feature.attributes = {}; |
---|
281 | this.feature = feature; |
---|
282 | this.symbolType = this.symbolTypeFromFeature(this.feature); |
---|
283 | if (!this.rules) { |
---|
284 | this.setRules(); |
---|
285 | } |
---|
286 | this.update(); |
---|
287 | }, |
---|
288 | |
---|
289 | /** private: method[setRules] |
---|
290 | * Sets the ``rules`` property for this. This is called when the component |
---|
291 | * is constructed without rules. Rules will be derived from the layer's |
---|
292 | * style map if it has one. |
---|
293 | */ |
---|
294 | setRules: function() { |
---|
295 | var style = this.layer.styleMap && this.layer.styleMap.styles["default"]; |
---|
296 | if (!style) { |
---|
297 | style = new OpenLayers.Style(); |
---|
298 | } |
---|
299 | if (style.rules.length === 0) { |
---|
300 | this.rules = [ |
---|
301 | new OpenLayers.Rule({ |
---|
302 | symbolizer: style.createSymbolizer(this.feature) |
---|
303 | }) |
---|
304 | ]; |
---|
305 | } else { |
---|
306 | this.rules = style.rules; |
---|
307 | } |
---|
308 | }, |
---|
309 | |
---|
310 | /** api: method[setCurrentScaleDenominator] |
---|
311 | * :arg scale: ``Number`` The scale denominator. |
---|
312 | * |
---|
313 | * Set the current scale denominator. This will hide entries for any |
---|
314 | * rules that don't apply at the current scale. |
---|
315 | */ |
---|
316 | setCurrentScaleDenominator: function(scale) { |
---|
317 | if (scale !== this.currentScaleDenominator) { |
---|
318 | this.currentScaleDenominator = scale; |
---|
319 | this.update(); |
---|
320 | } |
---|
321 | }, |
---|
322 | |
---|
323 | /** private: method[getRuleEntry] |
---|
324 | * :arg rule: ``OpenLayers.Rule`` |
---|
325 | * :returns: ``Ext.Container`` |
---|
326 | * |
---|
327 | * Get the item corresponding to the rule. |
---|
328 | */ |
---|
329 | getRuleEntry: function(rule) { |
---|
330 | return this.rulesContainer.items.get(this.rules.indexOf(rule)); |
---|
331 | }, |
---|
332 | |
---|
333 | /** private: method[addRuleEntry] |
---|
334 | * :arg rule: ``OpenLayers.Rule`` |
---|
335 | * :arg noDoLayout: ``Boolean`` Don't call doLayout after adding rule. |
---|
336 | * Default is ``false``. |
---|
337 | * |
---|
338 | * Add a new rule entry in the rules container. This |
---|
339 | * method does not add the rule to the rules array. |
---|
340 | */ |
---|
341 | addRuleEntry: function(rule, noDoLayout) { |
---|
342 | this.rulesContainer.add(this.createRuleEntry(rule)); |
---|
343 | if (!noDoLayout) { |
---|
344 | this.doLayout(); |
---|
345 | } |
---|
346 | }, |
---|
347 | |
---|
348 | /** private: method[removeRuleEntry] |
---|
349 | * :arg rule: ``OpenLayers.Rule`` |
---|
350 | * :arg noDoLayout: ``Boolean`` Don't call doLayout after removing rule. |
---|
351 | * Default is ``false``. |
---|
352 | * |
---|
353 | * Remove a rule entry from the rules container, this |
---|
354 | * method assumes the rule is in the rules array, and |
---|
355 | * it does not remove the rule from the rules array. |
---|
356 | */ |
---|
357 | removeRuleEntry: function(rule, noDoLayout) { |
---|
358 | var ruleEntry = this.getRuleEntry(rule); |
---|
359 | if (ruleEntry) { |
---|
360 | this.rulesContainer.remove(ruleEntry); |
---|
361 | if (!noDoLayout) { |
---|
362 | this.doLayout(); |
---|
363 | } |
---|
364 | } |
---|
365 | }, |
---|
366 | |
---|
367 | /** private: method[selectRuleEntry] |
---|
368 | */ |
---|
369 | selectRuleEntry: function(rule) { |
---|
370 | var newSelection = rule != this.selectedRule; |
---|
371 | if (this.selectedRule) { |
---|
372 | this.unselect(); |
---|
373 | } |
---|
374 | if (newSelection) { |
---|
375 | var ruleEntry = this.getRuleEntry(rule); |
---|
376 | ruleEntry.body.addClass("x-grid3-row-selected"); |
---|
377 | this.selectedRule = rule; |
---|
378 | this.fireEvent("ruleselected", this, rule); |
---|
379 | } |
---|
380 | }, |
---|
381 | |
---|
382 | /** private: method[unselect] |
---|
383 | */ |
---|
384 | unselect: function() { |
---|
385 | this.rulesContainer.items.each(function(item, i) { |
---|
386 | if (this.rules[i] == this.selectedRule) { |
---|
387 | item.body.removeClass("x-grid3-row-selected"); |
---|
388 | this.selectedRule = null; |
---|
389 | this.fireEvent("ruleunselected", this, this.rules[i]); |
---|
390 | } |
---|
391 | }, this); |
---|
392 | }, |
---|
393 | |
---|
394 | /** private: method[createRuleEntry] |
---|
395 | */ |
---|
396 | createRuleEntry: function(rule) { |
---|
397 | var applies = true; |
---|
398 | if (this.currentScaleDenominator != null) { |
---|
399 | if (rule.minScaleDenominator) { |
---|
400 | applies = applies && (this.currentScaleDenominator >= rule.minScaleDenominator); |
---|
401 | } |
---|
402 | if (rule.maxScaleDenominator) { |
---|
403 | applies = applies && (this.currentScaleDenominator < rule.maxScaleDenominator); |
---|
404 | } |
---|
405 | } |
---|
406 | return { |
---|
407 | xtype: "panel", |
---|
408 | layout: "column", |
---|
409 | border: false, |
---|
410 | hidden: !applies, |
---|
411 | bodyStyle: this.selectOnClick ? {cursor: "pointer"} : undefined, |
---|
412 | defaults: { |
---|
413 | border: false |
---|
414 | }, |
---|
415 | items: [ |
---|
416 | this.createRuleRenderer(rule), |
---|
417 | this.createRuleTitle(rule) |
---|
418 | ], |
---|
419 | listeners: { |
---|
420 | render: function(comp){ |
---|
421 | this.selectOnClick && comp.getEl().on({ |
---|
422 | click: function(comp){ |
---|
423 | this.selectRuleEntry(rule); |
---|
424 | }, |
---|
425 | scope: this |
---|
426 | }); |
---|
427 | if (this.enableDD == true) { |
---|
428 | this.addDD(comp); |
---|
429 | } |
---|
430 | }, |
---|
431 | scope: this |
---|
432 | } |
---|
433 | }; |
---|
434 | }, |
---|
435 | |
---|
436 | /** private: method[createRuleRenderer] |
---|
437 | * :arg rule: ``OpenLayers.Rule`` |
---|
438 | * :returns: ``GeoExt.FeatureRenderer`` |
---|
439 | * |
---|
440 | * Create a renderer for the rule. |
---|
441 | */ |
---|
442 | createRuleRenderer: function(rule) { |
---|
443 | var types = [this.symbolType, "Point", "Line", "Polygon"]; |
---|
444 | var type, haveType; |
---|
445 | var symbolizers = rule.symbolizers; |
---|
446 | if (!symbolizers) { |
---|
447 | // TODO: remove this when OpenLayers.Symbolizer is used everywhere |
---|
448 | var symbolizer = rule.symbolizer; |
---|
449 | for (var i=0, len=types.length; i<len; ++i) { |
---|
450 | type = types[i]; |
---|
451 | if (symbolizer[type]) { |
---|
452 | symbolizer = symbolizer[type]; |
---|
453 | haveType = true; |
---|
454 | break; |
---|
455 | } |
---|
456 | } |
---|
457 | symbolizers = [symbolizer]; |
---|
458 | } else { |
---|
459 | var Type; |
---|
460 | outer: for (var i=0, ii=types.length; i<ii; ++i) { |
---|
461 | type = types[i]; |
---|
462 | Type = OpenLayers.Symbolizer[type]; |
---|
463 | if (Type) { |
---|
464 | for (var j=0, jj=symbolizers.length; j<jj; ++j) { |
---|
465 | if (symbolizers[j] instanceof Type) { |
---|
466 | haveType = true; |
---|
467 | break outer; |
---|
468 | } |
---|
469 | } |
---|
470 | } |
---|
471 | } |
---|
472 | } |
---|
473 | return { |
---|
474 | xtype: "gx_renderer", |
---|
475 | symbolType: haveType ? type : this.symbolType, |
---|
476 | symbolizers: symbolizers, |
---|
477 | style: this.clickableSymbol ? {cursor: "pointer"} : undefined, |
---|
478 | listeners: { |
---|
479 | click: function() { |
---|
480 | if (this.clickableSymbol) { |
---|
481 | this.fireEvent("symbolclick", this, rule); |
---|
482 | this.fireEvent("ruleclick", this, rule); |
---|
483 | } |
---|
484 | }, |
---|
485 | scope: this |
---|
486 | } |
---|
487 | }; |
---|
488 | }, |
---|
489 | |
---|
490 | /** private: method[createRuleTitle] |
---|
491 | * :arg rule: ``OpenLayers.Rule`` |
---|
492 | * :returns: ``Ext.Component`` |
---|
493 | * |
---|
494 | * Create a title component for the rule. |
---|
495 | */ |
---|
496 | createRuleTitle: function(rule) { |
---|
497 | return { |
---|
498 | cls: "x-form-item", |
---|
499 | style: "padding: 0.2em 0.5em 0;", // TODO: css |
---|
500 | bodyStyle: Ext.applyIf({background: "transparent"}, |
---|
501 | this.clickableTitle ? {cursor: "pointer"} : undefined), |
---|
502 | html: this.getRuleTitle(rule), |
---|
503 | listeners: { |
---|
504 | render: function(comp) { |
---|
505 | this.clickableTitle && comp.getEl().on({ |
---|
506 | click: function() { |
---|
507 | this.fireEvent("titleclick", this, rule); |
---|
508 | this.fireEvent("ruleclick", this, rule); |
---|
509 | }, |
---|
510 | scope: this |
---|
511 | }); |
---|
512 | }, |
---|
513 | scope: this |
---|
514 | } |
---|
515 | }; |
---|
516 | }, |
---|
517 | |
---|
518 | /** private: method[addDD] |
---|
519 | * :arg component: ``Ext.Component`` |
---|
520 | * |
---|
521 | * Adds drag & drop functionality to a rule entry. |
---|
522 | */ |
---|
523 | addDD: function(component) { |
---|
524 | var ct = component.ownerCt; |
---|
525 | var panel = this; |
---|
526 | new Ext.dd.DragSource(component.getEl(), { |
---|
527 | ddGroup: ct.id, |
---|
528 | onDragOut: function(e, targetId) { |
---|
529 | var target = Ext.getCmp(targetId); |
---|
530 | target.removeClass("gx-ruledrag-insert-above"); |
---|
531 | target.removeClass("gx-ruledrag-insert-below"); |
---|
532 | return Ext.dd.DragZone.prototype.onDragOut.apply(this, arguments); |
---|
533 | }, |
---|
534 | onDragEnter: function(e, targetId) { |
---|
535 | var target = Ext.getCmp(targetId); |
---|
536 | var cls; |
---|
537 | var sourcePos = ct.items.indexOf(component); |
---|
538 | var targetPos = ct.items.indexOf(target); |
---|
539 | if (sourcePos > targetPos) { |
---|
540 | cls = "gx-ruledrag-insert-above"; |
---|
541 | } else if (sourcePos < targetPos) { |
---|
542 | cls = "gx-ruledrag-insert-below"; |
---|
543 | } |
---|
544 | cls && target.addClass(cls); |
---|
545 | return Ext.dd.DragZone.prototype.onDragEnter.apply(this, arguments); |
---|
546 | }, |
---|
547 | onDragDrop: function(e, targetId) { |
---|
548 | panel.moveRule(ct.items.indexOf(component), |
---|
549 | ct.items.indexOf(Ext.getCmp(targetId))); |
---|
550 | return Ext.dd.DragZone.prototype.onDragDrop.apply(this, arguments); |
---|
551 | }, |
---|
552 | getDragData: function(e) { |
---|
553 | var sourceEl = e.getTarget(".x-column-inner"); |
---|
554 | if(sourceEl) { |
---|
555 | var d = sourceEl.cloneNode(true); |
---|
556 | d.id = Ext.id(); |
---|
557 | return { |
---|
558 | sourceEl: sourceEl, |
---|
559 | repairXY: Ext.fly(sourceEl).getXY(), |
---|
560 | ddel: d |
---|
561 | } |
---|
562 | } |
---|
563 | } |
---|
564 | }); |
---|
565 | new Ext.dd.DropTarget(component.getEl(), { |
---|
566 | ddGroup: ct.id, |
---|
567 | notifyDrop: function() { |
---|
568 | return true; |
---|
569 | } |
---|
570 | }); |
---|
571 | }, |
---|
572 | |
---|
573 | /** api: method[update] |
---|
574 | * Update rule titles and symbolizers. |
---|
575 | */ |
---|
576 | update: function() { |
---|
577 | GeoExt.VectorLegend.superclass.update.apply(this, arguments); |
---|
578 | if (this.symbolType && this.rules) { |
---|
579 | if (this.rulesContainer.items) { |
---|
580 | var comp; |
---|
581 | for (var i=this.rulesContainer.items.length-1; i>=0; --i) { |
---|
582 | comp = this.rulesContainer.getComponent(i); |
---|
583 | this.rulesContainer.remove(comp, true); |
---|
584 | } |
---|
585 | } |
---|
586 | for (var i=0, ii=this.rules.length; i<ii; ++i) { |
---|
587 | this.addRuleEntry(this.rules[i], true); |
---|
588 | } |
---|
589 | this.doLayout(); |
---|
590 | // make sure that the selected rule is still selected after update |
---|
591 | if (this.selectedRule) { |
---|
592 | this.getRuleEntry(this.selectedRule).body.addClass("x-grid3-row-selected"); |
---|
593 | } |
---|
594 | } |
---|
595 | }, |
---|
596 | |
---|
597 | /** private: method[updateRuleEntry] |
---|
598 | * :arg rule: ``OpenLayers.Rule`` |
---|
599 | * |
---|
600 | * Update the renderer and the title of a rule. |
---|
601 | */ |
---|
602 | updateRuleEntry: function(rule) { |
---|
603 | var ruleEntry = this.getRuleEntry(rule); |
---|
604 | if (ruleEntry) { |
---|
605 | ruleEntry.removeAll(); |
---|
606 | ruleEntry.add(this.createRuleRenderer(rule)); |
---|
607 | ruleEntry.add(this.createRuleTitle(rule)); |
---|
608 | ruleEntry.doLayout(); |
---|
609 | } |
---|
610 | }, |
---|
611 | |
---|
612 | /** private: method[moveRule] |
---|
613 | */ |
---|
614 | moveRule: function(sourcePos, targetPos) { |
---|
615 | var srcRule = this.rules[sourcePos]; |
---|
616 | this.rules.splice(sourcePos, 1); |
---|
617 | this.rules.splice(targetPos, 0, srcRule); |
---|
618 | this.update(); |
---|
619 | this.fireEvent("rulemoved", this, srcRule); |
---|
620 | }, |
---|
621 | |
---|
622 | /** private: method[getRuleTitle] |
---|
623 | * :returns: ``String`` |
---|
624 | * |
---|
625 | * Get a rule title given a rule. |
---|
626 | */ |
---|
627 | getRuleTitle: function(rule) { |
---|
628 | var title = rule.title || rule.name || ""; |
---|
629 | if (!title && this.untitledPrefix) { |
---|
630 | title = this.untitledPrefix + (this.rules.indexOf(rule) + 1); |
---|
631 | } |
---|
632 | return title; |
---|
633 | }, |
---|
634 | |
---|
635 | /** private: method[beforeDestroy] |
---|
636 | * Override. |
---|
637 | */ |
---|
638 | beforeDestroy: function() { |
---|
639 | if (this.layer) { |
---|
640 | if (this.layer.events) { |
---|
641 | this.layer.events.un({ |
---|
642 | featuresadded: this.onFeaturesAdded, |
---|
643 | scope: this |
---|
644 | }); |
---|
645 | } |
---|
646 | if (this.layer.map && this.layer.map.events) { |
---|
647 | this.layer.map.events.un({ |
---|
648 | "zoomend": this.onMapZoom, |
---|
649 | scope: this |
---|
650 | }); |
---|
651 | } |
---|
652 | } |
---|
653 | delete this.layer; |
---|
654 | delete this.rules; |
---|
655 | GeoExt.VectorLegend.superclass.beforeDestroy.apply(this, arguments); |
---|
656 | } |
---|
657 | |
---|
658 | }); |
---|
659 | |
---|
660 | /** private: method[supports] |
---|
661 | * Private override |
---|
662 | */ |
---|
663 | GeoExt.VectorLegend.supports = function(layerRecord) { |
---|
664 | return layerRecord.getLayer() instanceof OpenLayers.Layer.Vector; |
---|
665 | }; |
---|
666 | |
---|
667 | /** api: legendtype = gx_vectorlegend */ |
---|
668 | GeoExt.LayerLegend.types["gx_vectorlegend"] = GeoExt.VectorLegend; |
---|
669 | |
---|
670 | /** api: xtype = gx_vectorlegend */ |
---|
671 | Ext.reg("gx_vectorlegend", GeoExt.VectorLegend); |
---|