X-Git-Url: http://git.ithinksw.org/extjs.git/blobdiff_plain/0494b8d9b9bb03ab6c22b34dae81261e3cd7e3e6..7a654f8d43fdb43d78b63d90528bed6e86b608cc:/src/draw/CompositeSprite.js diff --git a/src/draw/CompositeSprite.js b/src/draw/CompositeSprite.js new file mode 100644 index 00000000..4ed4ad53 --- /dev/null +++ b/src/draw/CompositeSprite.js @@ -0,0 +1,292 @@ +/** + * @class Ext.draw.CompositeSprite + * @extends Ext.util.MixedCollection + * + * A composite Sprite handles a group of sprites with common methods to a sprite + * such as `hide`, `show`, `setAttributes`. These methods are applied to the set of sprites + * added to the group. + * + * CompositeSprite extends {@link Ext.util.MixedCollection} so you can use the same methods + * in `MixedCollection` to iterate through sprites, add and remove elements, etc. + * + * In order to create a CompositeSprite, one has to provide a handle to the surface where it is + * rendered: + * + * var group = Ext.create('Ext.draw.CompositeSprite', { + * surface: drawComponent.surface + * }); + * + * Then just by using `MixedCollection` methods it's possible to add {@link Ext.draw.Sprite}s: + * + * group.add(sprite1); + * group.add(sprite2); + * group.add(sprite3); + * + * And then apply common Sprite methods to them: + * + * group.setAttributes({ + * fill: '#f00' + * }, true); + */ +Ext.define('Ext.draw.CompositeSprite', { + + /* Begin Definitions */ + + extend: 'Ext.util.MixedCollection', + mixins: { + animate: 'Ext.util.Animate' + }, + + /* End Definitions */ + isCompositeSprite: true, + constructor: function(config) { + var me = this; + + config = config || {}; + Ext.apply(me, config); + + me.addEvents( + 'mousedown', + 'mouseup', + 'mouseover', + 'mouseout', + 'click' + ); + me.id = Ext.id(null, 'ext-sprite-group-'); + me.callParent(); + }, + + // @private + onClick: function(e) { + this.fireEvent('click', e); + }, + + // @private + onMouseUp: function(e) { + this.fireEvent('mouseup', e); + }, + + // @private + onMouseDown: function(e) { + this.fireEvent('mousedown', e); + }, + + // @private + onMouseOver: function(e) { + this.fireEvent('mouseover', e); + }, + + // @private + onMouseOut: function(e) { + this.fireEvent('mouseout', e); + }, + + attachEvents: function(o) { + var me = this; + + o.on({ + scope: me, + mousedown: me.onMouseDown, + mouseup: me.onMouseUp, + mouseover: me.onMouseOver, + mouseout: me.onMouseOut, + click: me.onClick + }); + }, + + /** Add a Sprite to the Group */ + add: function(key, o) { + var result = this.callParent(arguments); + this.attachEvents(result); + return result; + }, + + insert: function(index, key, o) { + return this.callParent(arguments); + }, + + /** Remove a Sprite from the Group */ + remove: function(o) { + var me = this; + + o.un({ + scope: me, + mousedown: me.onMouseDown, + mouseup: me.onMouseUp, + mouseover: me.onMouseOver, + mouseout: me.onMouseOut, + click: me.onClick + }); + me.callParent(arguments); + }, + + /** + * Returns the group bounding box. + * Behaves like {@link Ext.draw.Sprite} getBBox method. + */ + getBBox: function() { + var i = 0, + sprite, + bb, + items = this.items, + len = this.length, + infinity = Infinity, + minX = infinity, + maxHeight = -infinity, + minY = infinity, + maxWidth = -infinity, + maxWidthBBox, maxHeightBBox; + + for (; i < len; i++) { + sprite = items[i]; + if (sprite.el) { + bb = sprite.getBBox(); + minX = Math.min(minX, bb.x); + minY = Math.min(minY, bb.y); + maxHeight = Math.max(maxHeight, bb.height + bb.y); + maxWidth = Math.max(maxWidth, bb.width + bb.x); + } + } + + return { + x: minX, + y: minY, + height: maxHeight - minY, + width: maxWidth - minX + }; + }, + + /** + * Iterates through all sprites calling + * `setAttributes` on each one. For more information + * {@link Ext.draw.Sprite} provides a description of the + * attributes that can be set with this method. + */ + setAttributes: function(attrs, redraw) { + var i = 0, + items = this.items, + len = this.length; + + for (; i < len; i++) { + items[i].setAttributes(attrs, redraw); + } + return this; + }, + + /** + * Hides all sprites. If the first parameter of the method is true + * then a redraw will be forced for each sprite. + */ + hide: function(attrs) { + var i = 0, + items = this.items, + len = this.length; + + for (; i < len; i++) { + items[i].hide(); + } + return this; + }, + + /** + * Shows all sprites. If the first parameter of the method is true + * then a redraw will be forced for each sprite. + */ + show: function(attrs) { + var i = 0, + items = this.items, + len = this.length; + + for (; i < len; i++) { + items[i].show(); + } + return this; + }, + + redraw: function() { + var me = this, + i = 0, + items = me.items, + surface = me.getSurface(), + len = me.length; + + if (surface) { + for (; i < len; i++) { + surface.renderItem(items[i]); + } + } + return me; + }, + + setStyle: function(obj) { + var i = 0, + items = this.items, + len = this.length, + item, el; + + for (; i < len; i++) { + item = items[i]; + el = item.el; + if (el) { + el.setStyle(obj); + } + } + }, + + addCls: function(obj) { + var i = 0, + items = this.items, + surface = this.getSurface(), + len = this.length; + + if (surface) { + for (; i < len; i++) { + surface.addCls(items[i], obj); + } + } + }, + + removeCls: function(obj) { + var i = 0, + items = this.items, + surface = this.getSurface(), + len = this.length; + + if (surface) { + for (; i < len; i++) { + surface.removeCls(items[i], obj); + } + } + }, + + /** + * Grab the surface from the items + * @private + * @return {Ext.draw.Surface} The surface, null if not found + */ + getSurface: function(){ + var first = this.first(); + if (first) { + return first.surface; + } + return null; + }, + + /** + * Destroys the SpriteGroup + */ + destroy: function(){ + var me = this, + surface = me.getSurface(), + item; + + if (surface) { + while (me.getCount() > 0) { + item = me.first(); + me.remove(item); + surface.remove(item); + } + } + me.clearListeners(); + } +});