You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
515 lines
16 KiB
515 lines
16 KiB
using System; |
|
using System.Collections.Generic; |
|
|
|
namespace FairyGUI |
|
{ |
|
public delegate void EventCallback0(); |
|
public delegate void EventCallback1(EventContext context); |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
public class EventDispatcher : IEventDispatcher |
|
{ |
|
Dictionary<string, EventBridge> _dic; |
|
|
|
public EventDispatcher() |
|
{ |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="callback"></param> |
|
public void AddEventListener(string strType, EventCallback1 callback) |
|
{ |
|
GetBridge(strType).Add(callback); |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="callback"></param> |
|
public void AddEventListener(string strType, EventCallback0 callback) |
|
{ |
|
GetBridge(strType).Add(callback); |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="callback"></param> |
|
public void RemoveEventListener(string strType, EventCallback1 callback) |
|
{ |
|
if (_dic == null) |
|
return; |
|
|
|
EventBridge bridge = null; |
|
if (_dic.TryGetValue(strType, out bridge)) |
|
bridge.Remove(callback); |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="callback"></param> |
|
public void RemoveEventListener(string strType, EventCallback0 callback) |
|
{ |
|
if (_dic == null) |
|
return; |
|
|
|
EventBridge bridge = null; |
|
if (_dic.TryGetValue(strType, out bridge)) |
|
bridge.Remove(callback); |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="callback"></param> |
|
public void AddCapture(string strType, EventCallback1 callback) |
|
{ |
|
GetBridge(strType).AddCapture(callback); |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="callback"></param> |
|
public void RemoveCapture(string strType, EventCallback1 callback) |
|
{ |
|
if (_dic == null) |
|
return; |
|
|
|
EventBridge bridge = null; |
|
if (_dic.TryGetValue(strType, out bridge)) |
|
bridge.RemoveCapture(callback); |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
public void RemoveEventListeners() |
|
{ |
|
RemoveEventListeners(null); |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
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<string, EventBridge> kv in _dic) |
|
kv.Value.Clear(); |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <returns></returns> |
|
public bool hasEventListeners(string strType) |
|
{ |
|
EventBridge bridge = TryGetEventBridge(strType); |
|
if (bridge == null) |
|
return false; |
|
|
|
return !bridge.isEmpty; |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <returns></returns> |
|
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<string, EventBridge>(); |
|
|
|
EventBridge bridge = null; |
|
if (!_dic.TryGetValue(strType, out bridge)) |
|
{ |
|
bridge = new EventBridge(this); |
|
_dic[strType] = bridge; |
|
} |
|
return bridge; |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <returns></returns> |
|
public bool DispatchEvent(string strType) |
|
{ |
|
return DispatchEvent(strType, null); |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="data"></param> |
|
/// <returns></returns> |
|
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; |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="context"></param> |
|
/// <returns></returns> |
|
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; |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="data"></param> |
|
/// <param name="addChain"></param> |
|
/// <returns></returns> |
|
internal bool BubbleEvent(string strType, object data, List<EventBridge> 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<EventBridge> 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; |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="data"></param> |
|
/// <returns></returns> |
|
public bool BubbleEvent(string strType, object data) |
|
{ |
|
return BubbleEvent(strType, data, null); |
|
} |
|
|
|
/// <summary> |
|
/// |
|
/// </summary> |
|
/// <param name="strType"></param> |
|
/// <param name="data"></param> |
|
/// <returns></returns> |
|
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<EventBridge> 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<string, EventBridge>(); |
|
|
|
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<EventBridge> 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<EventBridge> 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<EventBridge> 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); |
|
} |
|
} |
|
} |
|
} |
|
}
|
|
|