using System; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UIElements; namespace AV.UITK { public partial class FluentElement { public delegate void Call(TEvent evt, CallHandle c) where TEvent : EventBase, new(); static class EventStorage where TEvent : EventBase, new() { public static Dictionary, CallHandle> Handlers = new Dictionary, CallHandle>(); } /// Returns all callbacks registered to this element. public IEnumerable GetCallbacks() { return FluentUITK.GetCallbacks(x); } // TODO: OnBind // TODO: OnAnyChange public FluentElement OnChange(Call> evt) { Register(evt); return x; } public FluentElement OnChange(EventCallback> evt) { Register(evt); return x; } public FluentElement OnChange(Action evt) { Register>(_ => evt()); return x; } public FluentElement OnAttach(Call evt) { Register(evt); return x; } public FluentElement OnAttach(EventCallback evt) { Register(evt); return x; } public FluentElement OnAttach(Action evt) { Register(_ => evt()); return x; } public FluentElement OnLayoutUpdate(Call evt) { Register(evt); return x; } public FluentElement OnLayoutUpdate(EventCallback evt) { Register(evt); return x; } public FluentElement OnLayoutUpdate(Action evt) { Register(_ => evt()); return x; } public FluentElement OnClick(Action up) { OnClick((_, __) => up()); return x; } public FluentElement OnClick(Action up, MouseButton button) { OnClick((evt, c) => up(), (int)button); return x; } public FluentElement OnClick(EventCallback up) { OnClick((evt, _) => up(evt)); return x; } public FluentElement OnClick(EventCallback up, MouseButton button) { OnClick((evt, _) => up(evt), (int)button); return x; } public FluentElement OnClick(Call up) { // LMB is used as default value OnClick(up, 0); return x; } public FluentElement OnClick(Call up, MouseButton button) { OnClick(up, (int)button); return x; } FluentElement OnClick(Call up, int button) { var isMouseOver = false; // TODO: Could be improved by avoiding extra enter leave events? Register(evt => isMouseOver = true); Register(evt => isMouseOver = false); Register((evt, c) => { if (button != -1 && evt.button != button) return; if (isMouseOver) up.Invoke(evt, c); }); return x; } public FluentElement Register(EventCallback evt, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEvent : EventBase, new() { x.RegisterCallback(evt, trickleDown); return x; } public FluentElement Register(Call c, TrickleDown trickleDown = TrickleDown.NoTrickleDown) where TEvent : EventBase, new() { var handler = new CallHandle { x = x, eventTypeId = EventBase.TypeId() }; var callback = (EventCallback)(evt => { handler.evt = evt; handler.totalCalls++; handler.trickle = trickleDown; c.Invoke(evt, handler); }); handler.callback = callback; x.RegisterCallback(callback, trickleDown); if (EventStorage.Handlers.ContainsKey(c)) EventStorage.Handlers[c] = handler; else EventStorage.Handlers.Add(c, handler); return x; } public FluentElement Unregister(Call c) where TEvent : EventBase, new() { if (EventStorage.Handlers.TryGetValue(c, out var handler)) Unregister(handler); return x; } public FluentElement Unregister(EventCallback callback) where TEvent : EventBase, new() { x.UnregisterCallback(callback); return x; } public FluentElement Unregister(CallHandle handle) { FluentUITK.UnregisterCallback(x, handle.eventTypeId, handle.callback, handle.trickle); return x; } } }