using System; using System.Collections.Generic; namespace FairyGUI { public delegate void EventCallback0(); public delegate void EventCallback1(EventContext context); /// /// /// public class EventDispatcher : IEventDispatcher { Dictionary _dic; public EventDispatcher() { } /// /// /// /// /// public void AddEventListener(string strType, EventCallback1 callback) { GetBridge(strType).Add(callback); } /// /// /// /// /// public void AddEventListener(string strType, EventCallback0 callback) { GetBridge(strType).Add(callback); } /// /// /// /// /// public void RemoveEventListener(string strType, EventCallback1 callback) { if (_dic == null) return; EventBridge bridge = null; if (_dic.TryGetValue(strType, out bridge)) bridge.Remove(callback); } /// /// /// /// /// public void RemoveEventListener(string strType, EventCallback0 callback) { if (_dic == null) return; EventBridge bridge = null; if (_dic.TryGetValue(strType, out bridge)) bridge.Remove(callback); } /// /// /// /// /// public void AddCapture(string strType, EventCallback1 callback) { GetBridge(strType).AddCapture(callback); } /// /// /// /// /// public void RemoveCapture(string strType, EventCallback1 callback) { if (_dic == null) return; EventBridge bridge = null; if (_dic.TryGetValue(strType, out bridge)) bridge.RemoveCapture(callback); } /// /// /// public void RemoveEventListeners() { RemoveEventListeners(null); } /// /// /// /// public void RemoveEventListeners(string strType) { if (_dic == null) return; if (strType != null) { EventBridge bridge; if (_dic.TryGetValue(strType, out bridge)) bridge.Clear(); } else { foreach (KeyValuePair kv in _dic) kv.Value.Clear(); } } /// /// /// /// /// public bool hasEventListeners(string strType) { EventBridge bridge = TryGetEventBridge(strType); if (bridge == null) return false; return !bridge.isEmpty; } /// /// /// /// /// public bool isDispatching(string strType) { EventBridge bridge = TryGetEventBridge(strType); if (bridge == null) return false; return bridge._dispatching; } internal EventBridge TryGetEventBridge(string strType) { if (_dic == null) return null; EventBridge bridge = null; _dic.TryGetValue(strType, out bridge); return bridge; } internal EventBridge GetEventBridge(string strType) { if (_dic == null) _dic = new Dictionary(); EventBridge bridge = null; if (!_dic.TryGetValue(strType, out bridge)) { bridge = new EventBridge(this); _dic[strType] = bridge; } return bridge; } /// /// /// /// /// public bool DispatchEvent(string strType) { return DispatchEvent(strType, null); } /// /// /// /// /// /// public bool DispatchEvent(string strType, object data) { return InternalDispatchEvent(strType, null, data, null); } public bool DispatchEvent(string strType, object data, object initiator) { return InternalDispatchEvent(strType, null, data, initiator); } static InputEvent sCurrentInputEvent = new InputEvent(); internal bool InternalDispatchEvent(string strType, EventBridge bridge, object data, object initiator) { if (bridge == null) bridge = TryGetEventBridge(strType); EventBridge gBridge = null; if ((this is DisplayObject) && ((DisplayObject)this).gOwner != null) gBridge = ((DisplayObject)this).gOwner.TryGetEventBridge(strType); bool b1 = bridge != null && !bridge.isEmpty; bool b2 = gBridge != null && !gBridge.isEmpty; if (b1 || b2) { EventContext context = EventContext.Get(); context.initiator = initiator != null ? initiator : this; context.type = strType; context.data = data; if (data is InputEvent) sCurrentInputEvent = (InputEvent)data; context.inputEvent = sCurrentInputEvent; if (b1) { bridge.CallCaptureInternal(context); bridge.CallInternal(context); } if (b2) { gBridge.CallCaptureInternal(context); gBridge.CallInternal(context); } EventContext.Return(context); context.initiator = null; context.sender = null; context.data = null; return context._defaultPrevented; } else return false; } /// /// /// /// /// public bool DispatchEvent(EventContext context) { EventBridge bridge = TryGetEventBridge(context.type); EventBridge gBridge = null; if ((this is DisplayObject) && ((DisplayObject)this).gOwner != null) gBridge = ((DisplayObject)this).gOwner.TryGetEventBridge(context.type); EventDispatcher savedSender = context.sender; if (bridge != null && !bridge.isEmpty) { bridge.CallCaptureInternal(context); bridge.CallInternal(context); } if (gBridge != null && !gBridge.isEmpty) { gBridge.CallCaptureInternal(context); gBridge.CallInternal(context); } context.sender = savedSender; return context._defaultPrevented; } /// /// /// /// /// /// /// internal bool BubbleEvent(string strType, object data, List addChain) { EventContext context = EventContext.Get(); context.initiator = this; context.type = strType; context.data = data; if (data is InputEvent) sCurrentInputEvent = (InputEvent)data; context.inputEvent = sCurrentInputEvent; List bubbleChain = context.callChain; bubbleChain.Clear(); GetChainBridges(strType, bubbleChain, true); int length = bubbleChain.Count; for (int i = length - 1; i >= 0; i--) { bubbleChain[i].CallCaptureInternal(context); if (context._touchCapture) { context._touchCapture = false; if (strType == "onTouchBegin") Stage.inst.AddTouchMonitor(context.inputEvent.touchId, bubbleChain[i].owner); } } if (!context._stopsPropagation) { for (int i = 0; i < length; ++i) { bubbleChain[i].CallInternal(context); if (context._touchCapture) { context._touchCapture = false; if (strType == "onTouchBegin") Stage.inst.AddTouchMonitor(context.inputEvent.touchId, bubbleChain[i].owner); } if (context._stopsPropagation) break; } if (addChain != null) { length = addChain.Count; for (int i = 0; i < length; ++i) { EventBridge bridge = addChain[i]; if (bubbleChain.IndexOf(bridge) == -1) { bridge.CallCaptureInternal(context); bridge.CallInternal(context); } } } } EventContext.Return(context); context.initiator = null; context.sender = null; context.data = null; return context._defaultPrevented; } /// /// /// /// /// /// public bool BubbleEvent(string strType, object data) { return BubbleEvent(strType, data, null); } /// /// /// /// /// /// public bool BroadcastEvent(string strType, object data) { EventContext context = EventContext.Get(); context.initiator = this; context.type = strType; context.data = data; if (data is InputEvent) sCurrentInputEvent = (InputEvent)data; context.inputEvent = sCurrentInputEvent; List bubbleChain = context.callChain; bubbleChain.Clear(); if (this is Container) GetChildEventBridges(strType, (Container)this, bubbleChain); else if (this is GComponent) GetChildEventBridges(strType, (GComponent)this, bubbleChain); int length = bubbleChain.Count; for (int i = 0; i < length; ++i) bubbleChain[i].CallInternal(context); EventContext.Return(context); context.initiator = null; context.sender = null; context.data = null; return context._defaultPrevented; } EventBridge GetBridge(string strType) { if (strType == null) throw new Exception("event type cant be null"); if (_dic == null) _dic = new Dictionary(); EventBridge bridge = null; if (!_dic.TryGetValue(strType, out bridge)) { bridge = new EventBridge(this); _dic[strType] = bridge; } return bridge; } static void GetChildEventBridges(string strType, Container container, List bridges) { EventBridge bridge = container.TryGetEventBridge(strType); if (bridge != null) bridges.Add(bridge); if (container.gOwner != null) { bridge = container.gOwner.TryGetEventBridge(strType); if (bridge != null && !bridge.isEmpty) bridges.Add(bridge); } int count = container.numChildren; for (int i = 0; i < count; ++i) { DisplayObject obj = container.GetChildAt(i); if (obj is Container) GetChildEventBridges(strType, (Container)obj, bridges); else { bridge = obj.TryGetEventBridge(strType); if (bridge != null && !bridge.isEmpty) bridges.Add(bridge); if (obj.gOwner != null) { bridge = obj.gOwner.TryGetEventBridge(strType); if (bridge != null && !bridge.isEmpty) bridges.Add(bridge); } } } } static void GetChildEventBridges(string strType, GComponent container, List bridges) { EventBridge bridge = container.TryGetEventBridge(strType); if (bridge != null) bridges.Add(bridge); int count = container.numChildren; for (int i = 0; i < count; ++i) { GObject obj = container.GetChildAt(i); if (obj is GComponent) GetChildEventBridges(strType, (GComponent)obj, bridges); else { bridge = obj.TryGetEventBridge(strType); if (bridge != null) bridges.Add(bridge); } } } internal void GetChainBridges(string strType, List chain, bool bubble) { EventBridge bridge = TryGetEventBridge(strType); if (bridge != null && !bridge.isEmpty) chain.Add(bridge); if ((this is DisplayObject) && ((DisplayObject)this).gOwner != null) { bridge = ((DisplayObject)this).gOwner.TryGetEventBridge(strType); if (bridge != null && !bridge.isEmpty) chain.Add(bridge); } if (!bubble) return; if (this is DisplayObject) { DisplayObject element = (DisplayObject)this; while ((element = element.parent) != null) { bridge = element.TryGetEventBridge(strType); if (bridge != null && !bridge.isEmpty) chain.Add(bridge); if (element.gOwner != null) { bridge = element.gOwner.TryGetEventBridge(strType); if (bridge != null && !bridge.isEmpty) chain.Add(bridge); } } } else if (this is GObject) { GObject element = (GObject)this; while ((element = element.parent) != null) { bridge = element.TryGetEventBridge(strType); if (bridge != null && !bridge.isEmpty) chain.Add(bridge); } } } } }