Upgrade to ExtJS 4.0.2 - Released 06/09/2011
[extjs.git] / docs / source / Surface.html
1 <!DOCTYPE html>
2 <html>
3 <head>
4   <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5   <title>The source code</title>
6   <link href="../prettify/prettify.css" type="text/css" rel="stylesheet" />
7   <script type="text/javascript" src="../prettify/prettify.js"></script>
8   <style type="text/css">
9     .highlight { display: block; background-color: #ddd; }
10   </style>
11   <script type="text/javascript">
12     function highlight() {
13       document.getElementById(location.hash.replace(/#/, "")).className = "highlight";
14     }
15   </script>
16 </head>
17 <body onload="prettyPrint(); highlight();">
18   <pre class="prettyprint lang-js"><span id='Ext-draw-Surface'>/**
19 </span> * A Surface is an interface to render methods inside a draw {@link Ext.draw.Component}.
20  * A Surface contains methods to render sprites, get bounding boxes of sprites, add
21  * sprites to the canvas, initialize other graphic components, etc. One of the most used
22  * methods for this class is the `add` method, to add Sprites to the surface.
23  *
24  * Most of the Surface methods are abstract and they have a concrete implementation
25  * in VML or SVG engines.
26  *
27  * A Surface instance can be accessed as a property of a draw component. For example:
28  *
29  *     drawComponent.surface.add({
30  *         type: 'circle',
31  *         fill: '#ffc',
32  *         radius: 100,
33  *         x: 100,
34  *         y: 100
35  *     });
36  *
37  * The configuration object passed in the `add` method is the same as described in the {@link Ext.draw.Sprite}
38  * class documentation.
39  *
40  * # Listeners
41  *
42  * You can also add event listeners to the surface using the `Observable` listener syntax. Supported events are:
43  *
44  * - mousedown
45  * - mouseup
46  * - mouseover
47  * - mouseout
48  * - mousemove
49  * - mouseenter
50  * - mouseleave
51  * - click
52  *
53  * For example:
54  *
55  *     drawComponent.surface.on({
56  *        'mousemove': function() {
57  *             console.log('moving the mouse over the surface');   
58  *         }
59  *     });
60  *
61  * # Example
62  *
63  *     var drawComponent = Ext.create('Ext.draw.Component', {
64  *         width: 800,
65  *         height: 600,
66  *         renderTo: document.body
67  *     }), surface = drawComponent.surface;
68  *   
69  *     surface.add([{
70  *         type: 'circle',
71  *         radius: 10,
72  *         fill: '#f00',
73  *         x: 10,
74  *         y: 10,
75  *         group: 'circles'
76  *     }, {
77  *         type: 'circle',
78  *         radius: 10,
79  *         fill: '#0f0',
80  *         x: 50,
81  *         y: 50,
82  *         group: 'circles'
83  *     }, {
84  *         type: 'circle',
85  *         radius: 10,
86  *         fill: '#00f',
87  *         x: 100,
88  *         y: 100,
89  *         group: 'circles'
90  *     }, {
91  *         type: 'rect',
92  *         width: 20,
93  *         height: 20,
94  *         fill: '#f00',
95  *         x: 10,
96  *         y: 10,
97  *         group: 'rectangles'
98  *     }, {
99  *         type: 'rect',
100  *         width: 20,
101  *         height: 20,
102  *         fill: '#0f0',
103  *         x: 50,
104  *         y: 50,
105  *         group: 'rectangles'
106  *     }, {
107  *         type: 'rect',
108  *         width: 20,
109  *         height: 20,
110  *         fill: '#00f',
111  *         x: 100,
112  *         y: 100,
113  *         group: 'rectangles'
114  *     }]);
115  *   
116  *     // Get references to my groups
117  *     circles = surface.getGroup('circles');
118  *     rectangles = surface.getGroup('rectangles');
119  *
120  *     // Animate the circles down
121  *     circles.animate({
122  *         duration: 1000,
123  *         to: {
124  *             translate: {
125  *                 y: 200
126  *             }
127  *         }
128  *     });
129  *   
130  *     // Animate the rectangles across
131  *     rectangles.animate({
132  *         duration: 1000,
133  *         to: {
134  *             translate: {
135  *                 x: 200
136  *             }
137  *         }
138  *     });
139  */
140 Ext.define('Ext.draw.Surface', {
141
142     /* Begin Definitions */
143
144     mixins: {
145         observable: 'Ext.util.Observable'
146     },
147
148     requires: ['Ext.draw.CompositeSprite'],
149     uses: ['Ext.draw.engine.Svg', 'Ext.draw.engine.Vml'],
150
151     separatorRe: /[, ]+/,
152
153     statics: {
154 <span id='Ext-draw-Surface-method-create'>        /**
155 </span>         * Creates and returns a new concrete Surface instance appropriate for the current environment.
156          * @param {Object} config Initial configuration for the Surface instance
157          * @param {[String]} enginePriority Optional order of implementations to use; the first one that is
158          * available in the current environment will be used. Defaults to `['Svg', 'Vml']`.
159          * @return {Object} The created Surface or false.
160          * @static
161          */
162         create: function(config, enginePriority) {
163             enginePriority = enginePriority || ['Svg', 'Vml'];
164
165             var i = 0,
166                 len = enginePriority.length,
167                 surfaceClass;
168
169             for (; i &lt; len; i++) {
170                 if (Ext.supports[enginePriority[i]]) {
171                     return Ext.create('Ext.draw.engine.' + enginePriority[i], config);
172                 }
173             }
174             return false;
175         }
176     },
177
178     /* End Definitions */
179
180     // @private
181     availableAttrs: {
182         blur: 0,
183         &quot;clip-rect&quot;: &quot;0 0 1e9 1e9&quot;,
184         cursor: &quot;default&quot;,
185         cx: 0,
186         cy: 0,
187         'dominant-baseline': 'auto',
188         fill: &quot;none&quot;,
189         &quot;fill-opacity&quot;: 1,
190         font: '10px &quot;Arial&quot;',
191         &quot;font-family&quot;: '&quot;Arial&quot;',
192         &quot;font-size&quot;: &quot;10&quot;,
193         &quot;font-style&quot;: &quot;normal&quot;,
194         &quot;font-weight&quot;: 400,
195         gradient: &quot;&quot;,
196         height: 0,
197         hidden: false,
198         href: &quot;http://sencha.com/&quot;,
199         opacity: 1,
200         path: &quot;M0,0&quot;,
201         radius: 0,
202         rx: 0,
203         ry: 0,
204         scale: &quot;1 1&quot;,
205         src: &quot;&quot;,
206         stroke: &quot;#000&quot;,
207         &quot;stroke-dasharray&quot;: &quot;&quot;,
208         &quot;stroke-linecap&quot;: &quot;butt&quot;,
209         &quot;stroke-linejoin&quot;: &quot;butt&quot;,
210         &quot;stroke-miterlimit&quot;: 0,
211         &quot;stroke-opacity&quot;: 1,
212         &quot;stroke-width&quot;: 1,
213         target: &quot;_blank&quot;,
214         text: &quot;&quot;,
215         &quot;text-anchor&quot;: &quot;middle&quot;,
216         title: &quot;Ext Draw&quot;,
217         width: 0,
218         x: 0,
219         y: 0,
220         zIndex: 0
221     },
222
223 <span id='Ext-draw-Surface-cfg-height'>    /**
224 </span>     * @cfg {Number} height
225      * The height of this component in pixels (defaults to auto).
226      * **Note** to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
227      */
228 <span id='Ext-draw-Surface-cfg-width'>    /**
229 </span>     * @cfg {Number} width
230      * The width of this component in pixels (defaults to auto).
231      * **Note** to express this dimension as a percentage or offset see {@link Ext.Component#anchor}.
232      */
233
234     container: undefined,
235     height: 352,
236     width: 512,
237     x: 0,
238     y: 0,
239
240 <span id='Ext-draw-Surface-method-constructor'>    /**
241 </span>     * Creates new Surface.
242      * @param {Object} config (optional) Config object.
243      */
244     constructor: function(config) {
245         var me = this;
246         config = config || {};
247         Ext.apply(me, config);
248
249         me.domRef = Ext.getDoc().dom;
250         
251         me.customAttributes = {};
252
253         me.addEvents(
254             'mousedown',
255             'mouseup',
256             'mouseover',
257             'mouseout',
258             'mousemove',
259             'mouseenter',
260             'mouseleave',
261             'click'
262         );
263
264         me.mixins.observable.constructor.call(me);
265
266         me.getId();
267         me.initGradients();
268         me.initItems();
269         if (me.renderTo) {
270             me.render(me.renderTo);
271             delete me.renderTo;
272         }
273         me.initBackground(config.background);
274     },
275
276     // @private called to initialize components in the surface
277     // this is dependent on the underlying implementation.
278     initSurface: Ext.emptyFn,
279
280     // @private called to setup the surface to render an item
281     //this is dependent on the underlying implementation.
282     renderItem: Ext.emptyFn,
283
284     // @private
285     renderItems: Ext.emptyFn,
286
287     // @private
288     setViewBox: Ext.emptyFn,
289
290 <span id='Ext-draw-Surface-method-addCls'>    /**
291 </span>     * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
292      *
293      * For example:
294      *
295      *     drawComponent.surface.addCls(sprite, 'x-visible');
296      *
297      * @param {Object} sprite The sprite to add the class to.
298      * @param {String/[String]} className The CSS class to add, or an array of classes
299      * @method
300      */
301     addCls: Ext.emptyFn,
302
303 <span id='Ext-draw-Surface-method-removeCls'>    /**
304 </span>     * Removes one or more CSS classes from the element.
305      *
306      * For example:
307      *
308      *     drawComponent.surface.removeCls(sprite, 'x-visible');
309      *
310      * @param {Object} sprite The sprite to remove the class from.
311      * @param {String/[String]} className The CSS class to remove, or an array of classes
312      * @method
313      */
314     removeCls: Ext.emptyFn,
315
316 <span id='Ext-draw-Surface-method-setStyle'>    /**
317 </span>     * Sets CSS style attributes to an element.
318      *
319      * For example:
320      *
321      *     drawComponent.surface.setStyle(sprite, {
322      *         'cursor': 'pointer'
323      *     });
324      *
325      * @param {Object} sprite The sprite to add, or an array of classes to
326      * @param {Object} styles An Object with CSS styles.
327      * @method
328      */
329     setStyle: Ext.emptyFn,
330
331     // @private
332     initGradients: function() {
333         var gradients = this.gradients;
334         if (gradients) {
335             Ext.each(gradients, this.addGradient, this);
336         }
337     },
338
339     // @private
340     initItems: function() {
341         var items = this.items;
342         this.items = Ext.create('Ext.draw.CompositeSprite');
343         this.groups = Ext.create('Ext.draw.CompositeSprite');
344         if (items) {
345             this.add(items);
346         }
347     },
348     
349     // @private
350     initBackground: function(config) {
351         var me = this,
352             width = me.width,
353             height = me.height,
354             gradientId, gradient, backgroundSprite;
355         if (config) {
356             if (config.gradient) {
357                 gradient = config.gradient;
358                 gradientId = gradient.id;
359                 me.addGradient(gradient);
360                 me.background = me.add({
361                     type: 'rect',
362                     x: 0,
363                     y: 0,
364                     width: width,
365                     height: height,
366                     fill: 'url(#' + gradientId + ')'
367                 });
368             } else if (config.fill) {
369                 me.background = me.add({
370                     type: 'rect',
371                     x: 0,
372                     y: 0,
373                     width: width,
374                     height: height,
375                     fill: config.fill
376                 });
377             } else if (config.image) {
378                 me.background = me.add({
379                     type: 'image',
380                     x: 0,
381                     y: 0,
382                     width: width,
383                     height: height,
384                     src: config.image
385                 });
386             }
387         }
388     },
389     
390 <span id='Ext-draw-Surface-method-setSize'>    /**
391 </span>     * Sets the size of the surface. Accomodates the background (if any) to fit the new size too.
392      *
393      * For example:
394      *
395      *     drawComponent.surface.setSize(500, 500);
396      *
397      * This method is generally called when also setting the size of the draw Component.
398      * 
399      * @param {Number} w The new width of the canvas.
400      * @param {Number} h The new height of the canvas.
401      */
402     setSize: function(w, h) {
403         if (this.background) {
404             this.background.setAttributes({
405                 width: w,
406                 height: h,
407                 hidden: false
408             }, true);
409         }
410     },
411
412     // @private
413     scrubAttrs: function(sprite) {
414         var i,
415             attrs = {},
416             exclude = {},
417             sattr = sprite.attr;
418         for (i in sattr) {    
419             // Narrow down attributes to the main set
420             if (this.translateAttrs.hasOwnProperty(i)) {
421                 // Translated attr
422                 attrs[this.translateAttrs[i]] = sattr[i];
423                 exclude[this.translateAttrs[i]] = true;
424             }
425             else if (this.availableAttrs.hasOwnProperty(i) &amp;&amp; !exclude[i]) {
426                 // Passtrhough attr
427                 attrs[i] = sattr[i];
428             }
429         }
430         return attrs;
431     },
432
433     // @private
434     onClick: function(e) {
435         this.processEvent('click', e);
436     },
437
438     // @private
439     onMouseUp: function(e) {
440         this.processEvent('mouseup', e);
441     },
442
443     // @private
444     onMouseDown: function(e) {
445         this.processEvent('mousedown', e);
446     },
447
448     // @private
449     onMouseOver: function(e) {
450         this.processEvent('mouseover', e);
451     },
452
453     // @private
454     onMouseOut: function(e) {
455         this.processEvent('mouseout', e);
456     },
457
458     // @private
459     onMouseMove: function(e) {
460         this.fireEvent('mousemove', e);
461     },
462
463     // @private
464     onMouseEnter: Ext.emptyFn,
465
466     // @private
467     onMouseLeave: Ext.emptyFn,
468
469 <span id='Ext-draw-Surface-method-addGradient'>    /**
470 </span>     * Adds a gradient definition to the Surface. Note that in some surface engines, adding
471      * a gradient via this method will not take effect if the surface has already been rendered.
472      * Therefore, it is preferred to pass the gradients as an item to the surface config, rather
473      * than calling this method, especially if the surface is rendered immediately (e.g. due to
474      * 'renderTo' in its config). For more information on how to create gradients in the Chart
475      * configuration object please refer to {@link Ext.chart.Chart}.
476      *
477      * The gradient object to be passed into this method is composed by:
478      * 
479      * - **id** - string - The unique name of the gradient.
480      * - **angle** - number, optional - The angle of the gradient in degrees.
481      * - **stops** - object - An object with numbers as keys (from 0 to 100) and style objects as values.
482      *
483      * For example:
484      *
485      *    drawComponent.surface.addGradient({
486      *        id: 'gradientId',
487      *        angle: 45,
488      *        stops: {
489      *            0: {
490      *                color: '#555'
491      *            },
492      *            100: {
493      *                color: '#ddd'
494      *            }
495      *        }
496      *    });
497      *
498      * @method
499      */
500     addGradient: Ext.emptyFn,
501
502 <span id='Ext-draw-Surface-method-add'>    /**
503 </span>     * Adds a Sprite to the surface. See {@link Ext.draw.Sprite} for the configuration object to be
504      * passed into this method.
505      *
506      * For example:
507      *
508      *     drawComponent.surface.add({
509      *         type: 'circle',
510      *         fill: '#ffc',
511      *         radius: 100,
512      *         x: 100,
513      *         y: 100
514      *     });
515      *
516      */
517     add: function() {
518         var args = Array.prototype.slice.call(arguments),
519             sprite,
520             index;
521
522         var hasMultipleArgs = args.length &gt; 1;
523         if (hasMultipleArgs || Ext.isArray(args[0])) {
524             var items = hasMultipleArgs ? args : args[0],
525                 results = [],
526                 i, ln, item;
527
528             for (i = 0, ln = items.length; i &lt; ln; i++) {
529                 item = items[i];
530                 item = this.add(item);
531                 results.push(item);
532             }
533
534             return results;
535         }
536         sprite = this.prepareItems(args[0], true)[0];
537         this.normalizeSpriteCollection(sprite);
538         this.onAdd(sprite);
539         return sprite;
540     },
541
542 <span id='Ext-draw-Surface-method-normalizeSpriteCollection'>    /**
543 </span>     * @private
544      * Inserts or moves a given sprite into the correct position in the items
545      * MixedCollection, according to its zIndex. Will be inserted at the end of
546      * an existing series of sprites with the same or lower zIndex. If the sprite
547      * is already positioned within an appropriate zIndex group, it will not be moved.
548      * This ordering can be used by subclasses to assist in rendering the sprites in
549      * the correct order for proper z-index stacking.
550      * @param {Ext.draw.Sprite} sprite
551      * @return {Number} the sprite's new index in the list
552      */
553     normalizeSpriteCollection: function(sprite) {
554         var items = this.items,
555             zIndex = sprite.attr.zIndex,
556             idx = items.indexOf(sprite);
557
558         if (idx &lt; 0 || (idx &gt; 0 &amp;&amp; items.getAt(idx - 1).attr.zIndex &gt; zIndex) ||
559                 (idx &lt; items.length - 1 &amp;&amp; items.getAt(idx + 1).attr.zIndex &lt; zIndex)) {
560             items.removeAt(idx);
561             idx = items.findIndexBy(function(otherSprite) {
562                 return otherSprite.attr.zIndex &gt; zIndex;
563             });
564             if (idx &lt; 0) {
565                 idx = items.length;
566             }
567             items.insert(idx, sprite);
568         }
569         return idx;
570     },
571
572     onAdd: function(sprite) {
573         var group = sprite.group,
574             draggable = sprite.draggable,
575             groups, ln, i;
576         if (group) {
577             groups = [].concat(group);
578             ln = groups.length;
579             for (i = 0; i &lt; ln; i++) {
580                 group = groups[i];
581                 this.getGroup(group).add(sprite);
582             }
583             delete sprite.group;
584         }
585         if (draggable) {
586             sprite.initDraggable();
587         }
588     },
589
590 <span id='Ext-draw-Surface-method-remove'>    /**
591 </span>     * Removes a given sprite from the surface, optionally destroying the sprite in the process.
592      * You can also call the sprite own `remove` method.
593      *
594      * For example:
595      *
596      *     drawComponent.surface.remove(sprite);
597      *     //or...
598      *     sprite.remove();
599      *
600      * @param {Ext.draw.Sprite} sprite
601      * @param {Boolean} destroySprite
602      * @return {Number} the sprite's new index in the list
603      */
604     remove: function(sprite, destroySprite) {
605         if (sprite) {
606             this.items.remove(sprite);
607             this.groups.each(function(item) {
608                 item.remove(sprite);
609             });
610             sprite.onRemove();
611             if (destroySprite === true) {
612                 sprite.destroy();
613             }
614         }
615     },
616
617 <span id='Ext-draw-Surface-method-removeAll'>    /**
618 </span>     * Removes all sprites from the surface, optionally destroying the sprites in the process.
619      *
620      * For example:
621      *
622      *     drawComponent.surface.removeAll();
623      *
624      * @param {Boolean} destroySprites Whether to destroy all sprites when removing them.
625      * @return {Number} The sprite's new index in the list.
626      */
627     removeAll: function(destroySprites) {
628         var items = this.items.items,
629             ln = items.length,
630             i;
631         for (i = ln - 1; i &gt; -1; i--) {
632             this.remove(items[i], destroySprites);
633         }
634     },
635
636     onRemove: Ext.emptyFn,
637
638     onDestroy: Ext.emptyFn,
639
640     // @private
641     applyTransformations: function(sprite) {
642             sprite.bbox.transform = 0;
643             this.transform(sprite);
644
645         var me = this,
646             dirty = false,
647             attr = sprite.attr;
648
649         if (attr.translation.x != null || attr.translation.y != null) {
650             me.translate(sprite);
651             dirty = true;
652         }
653         if (attr.scaling.x != null || attr.scaling.y != null) {
654             me.scale(sprite);
655             dirty = true;
656         }
657         if (attr.rotation.degrees != null) {
658             me.rotate(sprite);
659             dirty = true;
660         }
661         if (dirty) {
662             sprite.bbox.transform = 0;
663             this.transform(sprite);
664             sprite.transformations = [];
665         }
666     },
667
668     // @private
669     rotate: function (sprite) {
670         var bbox,
671             deg = sprite.attr.rotation.degrees,
672             centerX = sprite.attr.rotation.x,
673             centerY = sprite.attr.rotation.y;
674         if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
675             bbox = this.getBBox(sprite);
676             centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
677             centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
678         }
679         sprite.transformations.push({
680             type: &quot;rotate&quot;,
681             degrees: deg,
682             x: centerX,
683             y: centerY
684         });
685     },
686
687     // @private
688     translate: function(sprite) {
689         var x = sprite.attr.translation.x || 0,
690             y = sprite.attr.translation.y || 0;
691         sprite.transformations.push({
692             type: &quot;translate&quot;,
693             x: x,
694             y: y
695         });
696     },
697
698     // @private
699     scale: function(sprite) {
700         var bbox,
701             x = sprite.attr.scaling.x || 1,
702             y = sprite.attr.scaling.y || 1,
703             centerX = sprite.attr.scaling.centerX,
704             centerY = sprite.attr.scaling.centerY;
705
706         if (!Ext.isNumber(centerX) || !Ext.isNumber(centerY)) {
707             bbox = this.getBBox(sprite);
708             centerX = !Ext.isNumber(centerX) ? bbox.x + bbox.width / 2 : centerX;
709             centerY = !Ext.isNumber(centerY) ? bbox.y + bbox.height / 2 : centerY;
710         }
711         sprite.transformations.push({
712             type: &quot;scale&quot;,
713             x: x,
714             y: y,
715             centerX: centerX,
716             centerY: centerY
717         });
718     },
719
720     // @private
721     rectPath: function (x, y, w, h, r) {
722         if (r) {
723             return [[&quot;M&quot;, x + r, y], [&quot;l&quot;, w - r * 2, 0], [&quot;a&quot;, r, r, 0, 0, 1, r, r], [&quot;l&quot;, 0, h - r * 2], [&quot;a&quot;, r, r, 0, 0, 1, -r, r], [&quot;l&quot;, r * 2 - w, 0], [&quot;a&quot;, r, r, 0, 0, 1, -r, -r], [&quot;l&quot;, 0, r * 2 - h], [&quot;a&quot;, r, r, 0, 0, 1, r, -r], [&quot;z&quot;]];
724         }
725         return [[&quot;M&quot;, x, y], [&quot;l&quot;, w, 0], [&quot;l&quot;, 0, h], [&quot;l&quot;, -w, 0], [&quot;z&quot;]];
726     },
727
728     // @private
729     ellipsePath: function (x, y, rx, ry) {
730         if (ry == null) {
731             ry = rx;
732         }
733         return [[&quot;M&quot;, x, y], [&quot;m&quot;, 0, -ry], [&quot;a&quot;, rx, ry, 0, 1, 1, 0, 2 * ry], [&quot;a&quot;, rx, ry, 0, 1, 1, 0, -2 * ry], [&quot;z&quot;]];
734     },
735
736     // @private
737     getPathpath: function (el) {
738         return el.attr.path;
739     },
740
741     // @private
742     getPathcircle: function (el) {
743         var a = el.attr;
744         return this.ellipsePath(a.x, a.y, a.radius, a.radius);
745     },
746
747     // @private
748     getPathellipse: function (el) {
749         var a = el.attr;
750         return this.ellipsePath(a.x, a.y,
751                                 a.radiusX || (a.width / 2) || 0,
752                                 a.radiusY || (a.height / 2) || 0);
753     },
754
755     // @private
756     getPathrect: function (el) {
757         var a = el.attr;
758         return this.rectPath(a.x, a.y, a.width, a.height, a.r);
759     },
760
761     // @private
762     getPathimage: function (el) {
763         var a = el.attr;
764         return this.rectPath(a.x || 0, a.y || 0, a.width, a.height);
765     },
766
767     // @private
768     getPathtext: function (el) {
769         var bbox = this.getBBoxText(el);
770         return this.rectPath(bbox.x, bbox.y, bbox.width, bbox.height);
771     },
772
773     createGroup: function(id) {
774         var group = this.groups.get(id);
775         if (!group) {
776             group = Ext.create('Ext.draw.CompositeSprite', {
777                 surface: this
778             });
779             group.id = id || Ext.id(null, 'ext-surface-group-');
780             this.groups.add(group);
781         }
782         return group;
783     },
784
785 <span id='Ext-draw-Surface-method-getGroup'>    /**
786 </span>     * Returns a new group or an existent group associated with the current surface.
787      * The group returned is a {@link Ext.draw.CompositeSprite} group.
788      *
789      * For example:
790      *
791      *     var spriteGroup = drawComponent.surface.getGroup('someGroupId');
792      *
793      * @param {String} id The unique identifier of the group.
794      * @return {Object} The {@link Ext.draw.CompositeSprite}.
795      */
796     getGroup: function(id) {
797         if (typeof id == &quot;string&quot;) {
798             var group = this.groups.get(id);
799             if (!group) {
800                 group = this.createGroup(id);
801             }
802         } else {
803             group = id;
804         }
805         return group;
806     },
807
808     // @private
809     prepareItems: function(items, applyDefaults) {
810         items = [].concat(items);
811         // Make sure defaults are applied and item is initialized
812         var item, i, ln;
813         for (i = 0, ln = items.length; i &lt; ln; i++) {
814             item = items[i];
815             if (!(item instanceof Ext.draw.Sprite)) {
816                 // Temporary, just take in configs...
817                 item.surface = this;
818                 items[i] = this.createItem(item);
819             } else {
820                 item.surface = this;
821             }
822         }
823         return items;
824     },
825     
826 <span id='Ext-draw-Surface-method-setText'>    /**
827 </span>     * Changes the text in the sprite element. The sprite must be a `text` sprite.
828      * This method can also be called from {@link Ext.draw.Sprite}.
829      *
830      * For example:
831      *
832      *     var spriteGroup = drawComponent.surface.setText(sprite, 'my new text');
833      *
834      * @param {Object} sprite The Sprite to change the text.
835      * @param {String} text The new text to be set.
836      * @method
837      */
838     setText: Ext.emptyFn,
839     
840     //@private Creates an item and appends it to the surface. Called
841     //as an internal method when calling `add`.
842     createItem: Ext.emptyFn,
843
844 <span id='Ext-draw-Surface-method-getId'>    /**
845 </span>     * Retrieves the id of this component.
846      * Will autogenerate an id if one has not already been set.
847      */
848     getId: function() {
849         return this.id || (this.id = Ext.id(null, 'ext-surface-'));
850     },
851
852 <span id='Ext-draw-Surface-method-destroy'>    /**
853 </span>     * Destroys the surface. This is done by removing all components from it and
854      * also removing its reference to a DOM element.
855      *
856      * For example:
857      *
858      *      drawComponent.surface.destroy();
859      */
860     destroy: function() {
861         delete this.domRef;
862         this.removeAll();
863     }
864 });</pre>
865 </body>
866 </html>