/**
* @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;
if (ln > 0) {
for (i = 0; i < ln; i++) {
publishers[i].subscribe(target, eventName);
}
}
return this.doAddListener.apply(this, arguments);
},
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;
if (ln > 0) {
for (i = 0; i < ln; i++) {
publishers[i].unsubscribe(target, eventName);
}
}
return this.doRemoveListener.apply(this, arguments);
},
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;
}
});