//@require @core /** * @private */ Ext.define('Ext.event.Dispatcher', { requires: [ 'Ext.event.ListenerStack', 'Ext.event.Controller' ], statics: { getInstance: function() { if (!this.instance) { this.instance = new this(); } return this.instance; }, setInstance: function(instance) { this.instance = instance; return this; } }, config: { publishers: {} }, wildcard: '*', constructor: function(config) { this.listenerStacks = {}; this.activePublishers = {}; this.publishersCache = {}; this.noActivePublishers = []; this.controller = null; this.initConfig(config); return this; }, getListenerStack: function(targetType, target, eventName, createIfNotExist) { var listenerStacks = this.listenerStacks, map = listenerStacks[targetType], listenerStack; createIfNotExist = Boolean(createIfNotExist); if (!map) { if (createIfNotExist) { listenerStacks[targetType] = map = {}; } else { return null; } } map = map[target]; if (!map) { if (createIfNotExist) { listenerStacks[targetType][target] = map = {}; } else { return null; } } listenerStack = map[eventName]; if (!listenerStack) { if (createIfNotExist) { map[eventName] = listenerStack = new Ext.event.ListenerStack(); } else { return null; } } return listenerStack; }, getController: function(targetType, target, eventName, connectedController) { var controller = this.controller, info = { targetType: targetType, target: target, eventName: eventName }; if (!controller) { this.controller = controller = new Ext.event.Controller(); } if (controller.isFiring) { controller = new Ext.event.Controller(); } controller.setInfo(info); if (connectedController && controller !== connectedController) { controller.connect(connectedController); } return controller; }, applyPublishers: function(publishers) { var i, publisher; this.publishersCache = {}; for (i in publishers) { if (publishers.hasOwnProperty(i)) { publisher = publishers[i]; this.registerPublisher(publisher); } } return publishers; }, registerPublisher: function(publisher) { var activePublishers = this.activePublishers, targetType = publisher.getTargetType(), publishers = activePublishers[targetType]; if (!publishers) { activePublishers[targetType] = publishers = []; } publishers.push(publisher); publisher.setDispatcher(this); return this; }, getCachedActivePublishers: function(targetType, eventName) { var cache = this.publishersCache, publishers; if ((publishers = cache[targetType]) && (publishers = publishers[eventName])) { return publishers; } return null; }, cacheActivePublishers: function(targetType, eventName, publishers) { var cache = this.publishersCache; if (!cache[targetType]) { cache[targetType] = {}; } cache[targetType][eventName] = publishers; return publishers; }, getActivePublishers: function(targetType, eventName) { var publishers, activePublishers, i, ln, publisher; if ((publishers = this.getCachedActivePublishers(targetType, eventName))) { return publishers; } activePublishers = this.activePublishers[targetType]; if (activePublishers) { publishers = []; for (i = 0,ln = activePublishers.length; i < ln; i++) { publisher = activePublishers[i]; if (publisher.handles(eventName)) { publishers.push(publisher); } } } else { publishers = this.noActivePublishers; } return this.cacheActivePublishers(targetType, eventName, publishers); }, hasListener: function(targetType, target, eventName) { var listenerStack = this.getListenerStack(targetType, target, eventName); if (listenerStack) { return listenerStack.count() > 0; } return false; }, addListener: function(targetType, target, eventName) { var publishers = this.getActivePublishers(targetType, eventName), ln = publishers.length, i, result; result = this.doAddListener.apply(this, arguments); if (result && ln > 0) { for (i = 0; i < ln; i++) { publishers[i].subscribe(target, eventName); } } return result; }, doAddListener: function(targetType, target, eventName, fn, scope, options, order) { var listenerStack = this.getListenerStack(targetType, target, eventName, true); return listenerStack.add(fn, scope, options, order); }, removeListener: function(targetType, target, eventName) { var publishers = this.getActivePublishers(targetType, eventName), ln = publishers.length, i, result; result = this.doRemoveListener.apply(this, arguments); if (result && ln > 0) { for (i = 0; i < ln; i++) { publishers[i].unsubscribe(target, eventName); } } return result; }, doRemoveListener: function(targetType, target, eventName, fn, scope, order) { var listenerStack = this.getListenerStack(targetType, target, eventName); if (listenerStack === null) { return false; } return listenerStack.remove(fn, scope, order); }, clearListeners: function(targetType, target, eventName) { var listenerStacks = this.listenerStacks, ln = arguments.length, stacks, publishers, i, publisherGroup; if (ln === 3) { if (listenerStacks[targetType] && listenerStacks[targetType][target]) { this.removeListener(targetType, target, eventName); delete listenerStacks[targetType][target][eventName]; } } else if (ln === 2) { if (listenerStacks[targetType]) { stacks = listenerStacks[targetType][target]; if (stacks) { for (eventName in stacks) { if (stacks.hasOwnProperty(eventName)) { publishers = this.getActivePublishers(targetType, eventName); for (i = 0,ln = publishers.length; i < ln; i++) { publishers[i].unsubscribe(target, eventName, true); } } } delete listenerStacks[targetType][target]; } } } else if (ln === 1) { publishers = this.activePublishers[targetType]; for (i = 0,ln = publishers.length; i < ln; i++) { publishers[i].unsubscribeAll(); } delete listenerStacks[targetType]; } else { publishers = this.activePublishers; for (targetType in publishers) { if (publishers.hasOwnProperty(targetType)) { publisherGroup = publishers[targetType]; for (i = 0,ln = publisherGroup.length; i < ln; i++) { publisherGroup[i].unsubscribeAll(); } } } delete this.listenerStacks; this.listenerStacks = {}; } return this; }, dispatchEvent: function(targetType, target, eventName) { var publishers = this.getActivePublishers(targetType, eventName), ln = publishers.length, i; if (ln > 0) { for (i = 0; i < ln; i++) { publishers[i].notify(target, eventName); } } return this.doDispatchEvent.apply(this, arguments); }, doDispatchEvent: function(targetType, target, eventName, args, action, connectedController) { var listenerStack = this.getListenerStack(targetType, target, eventName), wildcardStacks = this.getWildcardListenerStacks(targetType, target, eventName), controller; if ((listenerStack === null || listenerStack.length == 0)) { if (wildcardStacks.length == 0 && !action) { return; } } else { wildcardStacks.push(listenerStack); } controller = this.getController(targetType, target, eventName, connectedController); controller.setListenerStacks(wildcardStacks); controller.fire(args, action); return !controller.isInterrupted(); }, getWildcardListenerStacks: function(targetType, target, eventName) { var stacks = [], wildcard = this.wildcard, isEventNameNotWildcard = eventName !== wildcard, isTargetNotWildcard = target !== wildcard, stack; if (isEventNameNotWildcard && (stack = this.getListenerStack(targetType, target, wildcard))) { stacks.push(stack); } if (isTargetNotWildcard && (stack = this.getListenerStack(targetType, wildcard, eventName))) { stacks.push(stack); } return stacks; }, getPublisher: function (name) { return this.getPublishers()[name]; } });