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